﻿///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2023, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются 
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////

#Область СлужебныйПрограммныйИнтерфейс

// Свойства результата отчета (табличного документа и настроек) для контекстной настройки.
//
// Возвращаемое значение:
//   Структура:
//     * Заголовки - Соответствие
//     * ГраницыРазделов - см. ГраницыРазделовОтчета
//     * РолиПолей - см. РолиПолейОтчета
//     * ИндексПолей - см. ИндексПолейСтруктурыОтчета
//     * ОсновныеПоля - Массив из см. ОсновныеПоляОтчета
//     * ИтоговыеНастройки - НастройкиКомпоновкиДанных - см. синтакс-помощник КомпоновщикНастроекКомпоновкиДанных.ПолучитьНастройки();
//     * КомпоновщикНастроек - КомпоновщикНастроекКомпоновкиДанных - без выполнения метода РазвернутьАвтоПоля.
//     * КомпоновщикНастроекБезАвтоПолей - КомпоновщикНастроекКомпоновкиДанных - после выполнения метода РазвернутьАвтоПоля.
//     * МакетыОписаны - Булево
//     * ВремяФормирования - Число
//
Функция СвойстваРезультатаОтчета() Экспорт 
	
	СвойстваРезультата = Новый Структура;
	СвойстваРезультата.Вставить("АдресИндексаСтруктурыОтчета", Неопределено);
	СвойстваРезультата.Вставить("Заголовки", Новый Соответствие);
	СвойстваРезультата.Вставить("ГраницыРазделов", Новый СписокЗначений);
	СвойстваРезультата.Вставить("РолиПолей", Новый Структура);
	СвойстваРезультата.Вставить("ИндексПолей", Новый Соответствие);
	СвойстваРезультата.Вставить("ОсновныеПоля", Новый Массив);
	СвойстваРезультата.Вставить("ИтоговыеНастройки", Неопределено);
	СвойстваРезультата.Вставить("КомпоновщикНастроек", Неопределено);
	СвойстваРезультата.Вставить("КомпоновщикНастроекБезАвтоПолей", Неопределено);
	СвойстваРезультата.Вставить("МакетыОписаны", Ложь);
	СвойстваРезультата.Вставить("ВремяФормирования", 0);
	
	Возврат СвойстваРезультата;
	
КонецФункции

// Параметры:
//  Форма - ФормаКлиентскогоПриложения
//        - РасширениеУправляемойФормыДляОтчета
//
Процедура ИнициализироватьЗаголовкиОтчета(Форма) Экспорт 
	
	НастройкиОтчета = Форма.НастройкиОтчета; // см. ВариантыОтчетов.НастройкиФормыОтчета
	
	Если Не ВариантыОтчетовСлужебныйКлиентСервер.РежимВариантаОтчета(Форма.КлючТекущегоВарианта)
		Или Не НастройкиОтчета.РазрешеноИзменятьВарианты
		Или НастройкиОтчета.ОтключитьСтандартноеКонтекстноеМеню Тогда 
		
		Возврат;
	КонецЕсли;
	
	Заголовки = Новый Соответствие;
	
	Элементы = Форма.Элементы;
	СвойстваРезультата = НастройкиОтчета.СвойстваРезультата; // см. ВариантыОтчетовСлужебный.СвойстваРезультатаОтчета
	РезультатОтчета = Форма.ОтчетТабличныйДокумент; // ТабличныйДокумент
	
	ИндексСтруктурыОтчета = ИндексСтруктурыОтчета(Форма);
	ГраницаЗаголовкаРаздела = Неопределено;
	РазрезСвойствЗаголовков = СтандартныйРазрезСвойствЗаголовковОтчета();
	
	Для НомерСтроки = 1 По РезультатОтчета.ВысотаТаблицы Цикл 
		
		НачальнаяЯчейка = РезультатОтчета.Область(НомерСтроки, 1);
		
		Если ПрерватьСканированиеРезультатаОтчета(НачальнаяЯчейка, ИндексСтруктурыОтчета, ГраницаЗаголовкаРаздела) Тогда 
			Прервать;
		КонецЕсли;
		
		Если Не ЭтоЯчейкаЗаголовкаОтчета(НачальнаяЯчейка) Тогда 
			Продолжить;
		КонецЕсли;
		
		Для НомерКолонки = 1 По РезультатОтчета.ШиринаТаблицы Цикл 
			
			Ячейка = РезультатОтчета.Область(НомерСтроки, НомерКолонки);
			
			Если Не ЭтоЯчейкаЗаголовкаОтчета(Ячейка) Тогда 
				Продолжить;
			КонецЕсли;
			
			Если Форма.ПолучитьТекущийРежимОтображенияРезультата() = РежимОтображенияРезультатаОтчета.Обычный Тогда
				Ячейка.ГиперСсылка = Истина;
			КонецЕсли;
			
			ЗаполнитьЗначенияСвойств(РазрезСвойствЗаголовков.Добавить(), Ячейка);
			
			СвойстваЗаголовка = СтандартныеСвойстваЗаголовкаОтчета();
			ЗаполнитьЗначенияСвойств(СвойстваЗаголовка, Ячейка);
			
			Заголовки.Вставить(Ячейка.Имя, СвойстваЗаголовка);
			
		КонецЦикла;
		
	КонецЦикла;
	
	ОпределитьИерархиюЗаголовковОтчета(РазрезСвойствЗаголовков, Заголовки);
	ГраницыРазделов = ГраницыРазделовОтчета(РезультатОтчета, РазрезСвойствЗаголовков);
	
	ДополнитьСвойстваЗаголовковОтчета(Форма, РезультатОтчета, Заголовки, РазрезСвойствЗаголовков, ИндексСтруктурыОтчета, ГраницыРазделов);
	
	Ячейка = Элементы.ОтчетТабличныйДокумент.ТекущаяОбласть;
	
	Если Ячейка <> Неопределено Тогда 
		ВариантыОтчетовСлужебныйКлиентСервер.ОпределитьДоступностьДействийКонтекстногоМеню(Форма, Заголовки[Ячейка.Имя]);
	КонецЕсли;
	
	СвойстваРезультата.Заголовки = Заголовки;
	СвойстваРезультата.ГраницыРазделов = ГраницыРазделов;
	
КонецПроцедуры

// См. МультиязычностьСервер.ОбъектыСТЧПредставления
Процедура ПриОпределенииОбъектовСТабличнойЧастьюПредставление(Объекты) Экспорт
	Объекты.Добавить("Справочник.ВариантыОтчетов");
	Объекты.Добавить("Справочник.ПредопределенныеВариантыОтчетовРасширений");
КонецПроцедуры

// См. МультиязычностьСервер.ОбъектыСТЧПредставления
Процедура ПриОпределенииОбъектовСТабличнойЧастьюПредставлениеОбщиеДанные(Объекты) Экспорт
	Объекты.Добавить("Справочник.ПредопределенныеВариантыОтчетов");
КонецПроцедуры

#Область ПредставлениеНастроекКомпоновкиДанных

Функция ПредставлениеЭлементовСтруктуры(ЭлементыСтруктуры) Экспорт 
	
	ПредставлениеЭлементов = Новый Массив;
	
	Для Каждого Элемент Из ЭлементыСтруктуры Цикл 
		
		Если Не Элемент.Использование Тогда 
			Продолжить;
		КонецЕсли;
		
		ПредставлениеЭлемента = ПредставлениеЭлементаСтруктуры(Элемент);
		
		Если ЗначениеЗаполнено(ПредставлениеЭлемента) Тогда 
			ПредставлениеЭлементов.Добавить(ПредставлениеЭлемента);
		КонецЕсли;
		
	КонецЦикла;
	
	Возврат СтрСоединить(ПредставлениеЭлементов, ", ");
	
КонецФункции

Функция ПредставлениеЭлементаСтруктуры(Элемент) Экспорт 
	
	ПредставлениеЭлемента = "";
	
	Если ЗначениеЗаполнено(Элемент.ПредставлениеПользовательскойНастройки) Тогда 
		
		ПредставлениеЭлемента = Элемент.ПредставлениеПользовательскойНастройки;
		
	Иначе
		
		ТипЭлемента = ТипЗнч(Элемент);
		
		ПараметрИспользованияЗаголовка = Элемент.ПараметрыВывода.Элементы.Найти("ВыводитьЗаголовок");
		ПараметрЗаголовка = Элемент.ПараметрыВывода.Элементы.Найти("Заголовок");
		
		Если ЗначениеЗаполнено(ПараметрЗаголовка.Значение)
			И (ПараметрЗаголовка.Использование
			Или ПараметрИспользованияЗаголовка.Использование
			И ПараметрИспользованияЗаголовка.Значение <> ТипВыводаТекстаКомпоновкиДанных.НеВыводить) Тогда 
			
			ПредставлениеЭлемента = ПараметрЗаголовка.Значение;
			
		ИначеЕсли ТипЭлемента = Тип("ТаблицаКомпоновкиДанных") Тогда 
			
			ПредставлениеЭлемента = НСтр("ru = 'Таблица'");
			
		ИначеЕсли ТипЭлемента = Тип("ДиаграммаКомпоновкиДанных") Тогда 
			
			ПредставлениеЭлемента = НСтр("ru = 'Диаграмма'");
			
		ИначеЕсли ТипЭлемента = Тип("ГруппировкаКомпоновкиДанных")
			Или ТипЭлемента = Тип("ГруппировкаДиаграммыКомпоновкиДанных")
			Или ТипЭлемента = Тип("ГруппировкаТаблицыКомпоновкиДанных") Тогда 
			
			ПредставлениеЭлемента = ПредставлениеПолейГруппировки(Элемент);
			
		КонецЕсли;
		
	КонецЕсли;
	
	Возврат ПредставлениеЭлемента;
	
КонецФункции

Функция ПредставлениеПолейГруппировки(Группировка, ПометкаУдаления = Ложь) Экспорт 
	
	Если ЗначениеЗаполнено(Группировка.ПредставлениеПользовательскойНастройки) Тогда 
		Возврат Группировка.ПредставлениеПользовательскойНастройки;
	КонецЕсли;
	
	Поля = Группировка.ПоляГруппировки; // ПоляГруппировкиКомпоновкиДанных
	
	Если Поля.Элементы.Количество() = 0 Тогда 
		Возврат НСтр("ru = '<Детальные записи>'");
	КонецЕсли;
	
	ПредставлениеПолей = Новый Массив;
	
	Для Каждого Элемент Из Поля.Элементы Цикл 
		
		Если Не Элемент.Использование
			Или ТипЗнч(Элемент) = Тип("АвтоПолеГруппировкиКомпоновкиДанных") Тогда
			
			Продолжить;
		КонецЕсли;
		
		ОписаниеПоля = Поля.ДоступныеПоляПолейГруппировок.НайтиПоле(Элемент.Поле);
		
		Если ОписаниеПоля = Неопределено Тогда
			
			ПометкаУдаления = Истина;
			ПредставлениеПоля = Строка(Элемент.Поле);
			
		Иначе
			ПредставлениеПоля = ОписаниеПоля.Заголовок;
		КонецЕсли;
		
		Если Элемент.ТипГруппировки <> ТипГруппировкиКомпоновкиДанных.Элементы Тогда 
			ПредставлениеПоля = ПредставлениеПоля + " (" + Элемент.ТипГруппировки + ")";
		КонецЕсли;
		
		ПредставлениеПолей.Добавить(ПредставлениеПоля);
	КонецЦикла;
	
	Если ПредставлениеПолей.Количество() = 0 Тогда 
		Возврат НСтр("ru = '<Детальные записи>'");
	КонецЕсли;
	
	Возврат СтрСоединить(ПредставлениеПолей, ", ");
	
КонецФункции

Функция ПредставлениеВыбранныхПолей(ВыбранныеПоля, Коллекция = Неопределено, ПредставлениеПолей = Неопределено) Экспорт 
	
	Если ЗначениеЗаполнено(ВыбранныеПоля.ПредставлениеПользовательскойНастройки) Тогда 
		Возврат ВыбранныеПоля.ПредставлениеПользовательскойНастройки;
	КонецЕсли;
	
	Если Коллекция = Неопределено Тогда 
		Коллекция = ВыбранныеПоля;
	КонецЕсли;
	
	Если ПредставлениеПолей = Неопределено Тогда 
		ПредставлениеПолей = Новый Массив;
	КонецЕсли;
	
	Для Каждого Элемент Из Коллекция.Элементы Цикл 
		
		Если Не Элемент.Использование Тогда 
			Продолжить;
		КонецЕсли;
		
		Если ТипЗнч(Элемент) = Тип("АвтоВыбранноеПолеКомпоновкиДанных") Тогда 
			
			ПредставлениеПолей.Добавить(НСтр("ru = 'Авто'"));
			
		ИначеЕсли ТипЗнч(Элемент) = Тип("ГруппаВыбранныхПолейКомпоновкиДанных") Тогда 
			
			ПредставлениеВыбранныхПолей(ВыбранныеПоля, Элемент, ПредставлениеПолей);
			
		ИначеЕсли ЗначениеЗаполнено(Элемент.Заголовок) Тогда 
			
			ПредставлениеПолей.Добавить(Элемент.Заголовок);
			
		Иначе
			
			ОписаниеПоля = ВыбранныеПоля.ДоступныеПоляВыбора.НайтиПоле(Элемент.Поле); // ДоступноеПолеКомпоновкиДанных
			
			ПредставлениеПоля = ?(ОписаниеПоля = Неопределено, Строка(Элемент.Поле), ОписаниеПоля.Заголовок);
			ПредставлениеПолей.Добавить(ПредставлениеПоля);
			
		КонецЕсли;
		
	КонецЦикла;
	
	Возврат СтрСоединить(ПредставлениеПолей, ", ");
	
КонецФункции

Функция ПредставлениеУсловногоОформления(УсловноеОформление) Экспорт 
	
	ПредставлениеОформления = Новый Массив;
	
	Для Каждого Элемент Из УсловноеОформление.Элементы Цикл 
		
		Если Не Элемент.Использование Тогда 
			Продолжить;
		КонецЕсли;
		
		ПредставлениеЭлемента = ОтчетыКлиентСервер.ПредставлениеЭлементаУсловногоОформления(Элемент, Неопределено, "");
		
		Если ЗначениеЗаполнено(ПредставлениеЭлемента) Тогда 
			ПредставлениеОформления.Добавить(ПредставлениеЭлемента);
		КонецЕсли;
		
	КонецЦикла;
	
	Если ПредставлениеОформления.Количество() = 0 Тогда 
		Возврат НСтр("ru = 'Оформление'");
	КонецЕсли;
	
	Возврат СтрСоединить(ПредставлениеОформления, ", ");
	
КонецФункции

// Параметры:
//  Сортировка - ПорядокКомпоновкиДанных
// 
// Возвращаемое значение:
//  Строка 
//
Функция ПредставлениеСортировки(Сортировка) Экспорт 
	
	ПредставлениеСортировки = Новый Массив;
	
	Для Каждого Элемент Из Сортировка.Элементы Цикл 
		
		Если Не Элемент.Использование Тогда 
			Продолжить;
		КонецЕсли;
		
		ПредставлениеЭлемента = ПредставлениеЭлементаСортировки(Элемент, Сортировка);
		
		Если ЗначениеЗаполнено(ПредставлениеЭлемента) Тогда 
			ПредставлениеСортировки.Добавить(ПредставлениеЭлемента);
		КонецЕсли;
		
	КонецЦикла;
	
	Если ПредставлениеСортировки.Количество() = 0 Тогда 
		Возврат НСтр("ru = 'Сортировка'");
	КонецЕсли;
	
	Возврат СтрСоединить(ПредставлениеСортировки, ", ");
	
КонецФункции

// Параметры:
//  Элемент - ЭлементПорядкаКомпоновкиДанных, АвтоЭлементПорядкаКомпоновкиДанных
//  Сортировка - Неопределено, ПорядокКомпоновкиДанных
// 
// Возвращаемое значение:
//  Строка
//
Функция ПредставлениеЭлементаСортировки(Элемент, Сортировка = Неопределено) Экспорт 
	
	Заголовок = "";
	
	Если Не Элемент.Использование Тогда 
		Возврат Заголовок;
	КонецЕсли;
	
	Если ТипЗнч(Элемент) = Тип("АвтоЭлементПорядкаКомпоновкиДанных") Тогда 
		Возврат НСтр("ru = 'Авто'");
	КонецЕсли;
	
	Если ТипЗнч(Сортировка) = Тип("ПорядокКомпоновкиДанных") Тогда
		ОписаниеНастройки = Сортировка.ДоступныеПоляПорядка.НайтиПоле(Элемент.Поле);
		Если ОписаниеНастройки <> Неопределено Тогда
			Заголовок = ОписаниеНастройки.Заголовок;
		КонецЕсли;
	КонецЕсли;
	
	Если ПустаяСтрока(Заголовок) Тогда
		Заголовок = Строка(Элемент.Поле);
	КонецЕсли;
	
	Если Элемент.ТипУпорядочивания = НаправлениеСортировкиКомпоновкиДанных.Возр Тогда 
		Возврат Заголовок;
	КонецЕсли;
	
	Возврат СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = '%1 (убыв)'"), Заголовок);
	
КонецФункции

Функция ПустоеНазначениеВариантаОтчета() Экспорт
	
	Возврат ПредопределенноеЗначение("Перечисление.НазначенияВариантовОтчетов.ПустаяСсылка");
	
КонецФункции

// Определяет назначение варианта отчета по умолчанию.
// Возвращаемое значение:
//  ПеречислениеСсылка.НазначенияВариантовОтчетов
//
Функция НазначениеВариантаОтчетаПоУмолчанию() Экспорт
	Возврат Перечисления.НазначенияВариантовОтчетов.ДляКомпьютеровИПланшетов;
КонецФункции

#КонецОбласти

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

Функция КлючЗамеров(ПолноеИмяОтчета, КлючВарианта) Экспорт
	Возврат ОбщегоНазначения.СократитьСтрокуКонтрольнойСуммой(
		ПолноеИмяОтчета + "." + КлючВарианта, 135);
КонецФункции

#Область ИндексацияРазделовОтчета

Функция ИндексСтруктурыОтчета(Форма) Экспорт
	
	НастройкиОтчета = Форма.НастройкиОтчета;
	СвойстваРезультата = НастройкиОтчета.СвойстваРезультата;
	
	Настройки = Форма.Отчет.КомпоновщикНастроек.ПолучитьНастройки();
	
	КомпоновщикНастроек = КопияКомпоновщикаНастроек(Форма.Отчет.КомпоновщикНастроек,
		НастройкиОтчета.АдресСхемы, Настройки);
	
	КомпоновщикНастроек2 = КопияКомпоновщикаНастроек(Форма.Отчет.КомпоновщикНастроек,
		НастройкиОтчета.АдресСхемы, Настройки);
	
	КомпоновщикНастроек2.РазвернутьАвтоПоля();
	Настройки2 = КомпоновщикНастроек2.ПолучитьНастройки();
	
	СвойстваРезультата.ИтоговыеНастройки = Настройки;
	СвойстваРезультата.КомпоновщикНастроек = КомпоновщикНастроек;
	СвойстваРезультата.КомпоновщикНастроекБезАвтоПолей = КомпоновщикНастроек2;
	СвойстваРезультата.РолиПолей = РолиПолейОтчета(НастройкиОтчета.АдресСхемы);
	
	ИндексСтруктурыОтчета = Неопределено;
	
	Если ЭтоАдресВременногоХранилища(СвойстваРезультата.АдресИндексаСтруктурыОтчета) Тогда 
		ИндексСтруктурыОтчета = ПолучитьИзВременногоХранилища(СвойстваРезультата.АдресИндексаСтруктурыОтчета);
	КонецЕсли;
	
	Если ИндексСтруктурыОтчета = Неопределено
		Или Форма.ВариантМодифицирован Тогда 
		
		ИндексСтруктурыОтчета = ИндексСтруктурыОтчетаБезКонтекста(Настройки, Настройки2);
		
		ОпределитьРолиПолей(ИндексСтруктурыОтчета, СвойстваРезультата.РолиПолей);
		ОпределитьПоляФормулы(НастройкиОтчета.АдресСхемы, Настройки, ИндексСтруктурыОтчета);
		УстановитьИдентификаторыИндексаСтруктурыОтчета(ИндексСтруктурыОтчета);
		ОпределитьДоступныеДействияПолейОтчета(ИндексСтруктурыОтчета);
		
		СвойстваРезультата.АдресИндексаСтруктурыОтчета = ПоместитьВоВременноеХранилище(
			ИндексСтруктурыОтчета, Форма.УникальныйИдентификатор);
		
		ЗаполнитьСвойстваМакетовЗаголовковОтчета(НастройкиОтчета.АдресСхемы, ИндексСтруктурыОтчета);
		ИндексСтруктурыОтчета.Индексы.Добавить("ПорядокРаздела, ПредставлениеПоля, Текст");
		
	КонецЕсли;
	
	СвойстваРезультата.ИндексПолей = ИндексПолейСтруктурыОтчета(ИндексСтруктурыОтчета);
	СвойстваРезультата.ОсновныеПоля = ОсновныеПоляОтчета(Форма);
	СвойстваРезультата.МакетыОписаны = МакетыКомпоновкиДанныхОписаны(НастройкиОтчета.АдресСхемы);
	
	Возврат ИндексСтруктурыОтчета;
	
КонецФункции

Функция КопияКомпоновщикаНастроек(ТекущийКомпоновщикНастроек, АдресСхемы, ИтоговыеНастройки)
	
	КомпоновщикНастроек = Новый КомпоновщикНастроекКомпоновкиДанных;
	ОтчетыСервер.ИнициализироватьКомпоновщикНастроек(КомпоновщикНастроек, АдресСхемы);
	КомпоновщикНастроек.ЗагрузитьНастройки(ИтоговыеНастройки);
	
	СкопироватьДополнительныеСвойстваНастроек(КомпоновщикНастроек, ТекущийКомпоновщикНастроек);
	
	Возврат КомпоновщикНастроек;
	
КонецФункции

Функция ИндексСтруктурыОтчетаБезКонтекста(Настройки, Настройки2) Экспорт 
	
	ИндексСтруктурыОтчета = НовыйИндексСтруктурыОтчета();
	ИндексироватьРазделыОтчета(Настройки2, Настройки2, ИндексСтруктурыОтчета);
	ИндексироватьГруппировкиОтчета(Настройки, Настройки2, ИндексСтруктурыОтчета);
	
	УдалитьНеидентифицированныеПоля(ИндексСтруктурыОтчета);
	УточнитьПорядокРазделов(ИндексСтруктурыОтчета);
	
	Возврат ИндексСтруктурыОтчета;
	
КонецФункции

Процедура СкопироватьДополнительныеСвойстваНастроек(Приемник, Источник)
	
	ВидыНастроек = СтрРазделить("Настройки, ПользовательскиеНастройки", ", ", Ложь);
	
	Для Каждого ВидНастроек Из ВидыНастроек Цикл 
		
		СвойстваИсточника = Источник[ВидНастроек].ДополнительныеСвойства;
		
		СвойстваПриемника = Приемник[ВидНастроек].ДополнительныеСвойства;
		СвойстваПриемника.Очистить();
		
		Для Каждого Свойство Из СвойстваИсточника Цикл 
			СвойстваПриемника.Вставить(Свойство.Ключ, Свойство.Значение);
		КонецЦикла;
		
	КонецЦикла;
	
КонецПроцедуры

Процедура ИндексироватьРазделыОтчета(ИтоговыеНастройки, Настройки, ИндексСтруктурыОтчета, ПорядокРаздела = 0)
	
	Для Каждого Раздел Из Настройки.Структура Цикл 
		
		Если Не Раздел.Использование
			Или ТипЗнч(Раздел) = Тип("ДиаграммаКомпоновкиДанных") Тогда 
			
			Продолжить;
		КонецЕсли;
		
		Если ТипЗнч(Раздел) = Тип("НастройкиВложенногоОбъектаКомпоновкиДанных") Тогда 
			
			ИндексироватьРазделыОтчета(ИтоговыеНастройки, Раздел.Настройки, ИндексСтруктурыОтчета, ПорядокРаздела);
		
		Иначе
			
			ПорядокРаздела = ПорядокРаздела + 1;
			
			ИндексРаздела = ИндексСтруктурыОтчета.Добавить();
			ИндексРаздела.ПорядокРаздела = ПорядокРаздела;
			ИндексРаздела.ИдентификаторНастроек = ИтоговыеНастройки.ПолучитьИдентификаторПоОбъекту(Настройки);
			ИндексРаздела.ИдентификаторРаздела = Настройки.ПолучитьИдентификаторПоОбъекту(Раздел);
			
		КонецЕсли;
		
	КонецЦикла;
	
КонецПроцедуры

// Параметры:
//  ИндексРазделовОтчетов - см. НовыйИндексСтруктурыОтчета
// 
// Возвращаемое значение:
//  Структура:
//   * ИндексСтруктурыОтчета - см. НовыйИндексСтруктурыОтчета
//   * ПорядокГруппировки - Число
//   * ПорядокПоля - Число
//   * ПоляСортировки - Соответствие
//
Функция НовыйКонтекстИндексацииГруппировкиОтчета(ИндексСтруктурыОтчета)
	
	Контекст = Новый Структура;
	Контекст.Вставить("ИндексСтруктурыОтчета", ИндексСтруктурыОтчета);
	Контекст.Вставить("ПорядокГруппировки", 0);
	Контекст.Вставить("ПорядокПоля", 0);
	Контекст.Вставить("ПоляСортировки", Новый Соответствие);
	
	Возврат Контекст;
	
КонецФункции

Процедура ИндексироватьГруппировкиОтчета(ИтоговыеНастройки, ИтоговыеНастройки2, ИндексСтруктурыОтчета)
	
	ИндексРазделовОтчетов = ИндексСтруктурыОтчета.Скопировать();
	
	Для Каждого ИндексРаздела Из ИндексРазделовОтчетов Цикл 
		
		Настройки = ИтоговыеНастройки.ПолучитьОбъектПоИдентификатору(ИндексРаздела.ИдентификаторНастроек);
		Настройки2 = ИтоговыеНастройки2.ПолучитьОбъектПоИдентификатору(ИндексРаздела.ИдентификаторНастроек);
		Раздел = Настройки.ПолучитьОбъектПоИдентификатору(ИндексРаздела.ИдентификаторРаздела); // ГруппировкаКомпоновкиДанных, ТаблицаКомпоновкиДанных
		Раздел2 = Настройки2.ПолучитьОбъектПоИдентификатору(ИндексРаздела.ИдентификаторРаздела); // ГруппировкаКомпоновкиДанных, ТаблицаКомпоновкиДанных
		
		Если ТипЗнч(Раздел2) = Тип("ДиаграммаКомпоновкиДанных") Тогда 
			Продолжить;
		КонецЕсли;
		
		Контекст = НовыйКонтекстИндексацииГруппировкиОтчета(ИндексСтруктурыОтчета);
		
		ПоляСортировки(Настройки, Настройки, Контекст.ПоляСортировки);
		
		Если ТипЗнч(Раздел2) = Тип("ТаблицаКомпоновкиДанных") Тогда 
			ИндексироватьГруппировкиРазделаОтчета(Контекст, ИндексРаздела,
				Настройки, Раздел.Строки, Настройки2, Раздел2.Строки);
			
			ИндексироватьГруппировкиРазделаОтчета(Контекст, ИндексРаздела,
				Настройки, Раздел.Колонки, Настройки2, Раздел2.Колонки);
		Иначе
			ИндексГруппировки = ИндексГруппировкиОтчета(Контекст, ИндексРаздела, Настройки2, Раздел2);
			
			ПоляСортировки(Раздел, Настройки, Контекст.ПоляСортировки);
			
			ИндексироватьПоляГруппировкиОтчета(Контекст, ИндексГруппировки,
				Настройки, Раздел, Настройки2, Раздел2);
			
			ИндексироватьГруппировкиРазделаОтчета(Контекст, ИндексРаздела,
				Настройки, Раздел.Структура, Настройки2, Раздел2.Структура);
		КонецЕсли;
		
	КонецЦикла;
	
КонецПроцедуры

Процедура ИндексироватьГруппировкиРазделаОтчета(Контекст, ИндексРаздела,
			Настройки, Группировки, Настройки2, Группировки2)
	
	Для НомерГруппировки = 1 По Группировки2.Количество() Цикл
		Элемент = Группировки[НомерГруппировки - 1];
		Элемент2 = Группировки2[НомерГруппировки - 1];
		
		Если Не Элемент2.Использование Тогда 
			Продолжить;
		КонецЕсли;
		
		ТипЭлемента = ТипЗнч(Элемент2);
		
		Если ТипЭлемента = Тип("НастройкиВложенногоОбъектаКомпоновкиДанных") Тогда 
			
			ИндексироватьГруппировкиРазделаОтчета(Контекст, ИндексРаздела,
				Элемент.Настройки, Элемент.Настройки.Структура, Элемент2.Настройки, Элемент2.Настройки.Структура);
			
		ИначеЕсли ТипЭлемента = Тип("ТаблицаКомпоновкиДанных") Тогда 
			
			ИндексироватьГруппировкиРазделаОтчета(Контекст, ИндексРаздела,
				Настройки, Элемент.Строки, Настройки2, Элемент2.Строки);
			
			ИндексироватьГруппировкиРазделаОтчета(Контекст, ИндексРаздела,
				Настройки, Элемент.Колонки, Настройки2, Элемент2.Колонки);
			
		ИначеЕсли ТипЭлемента <> Тип("ДиаграммаКомпоновкиДанных") Тогда 
			
			ПоляСортировки(Элемент, Настройки, Контекст.ПоляСортировки);
			
			ИндексГруппировки = ИндексГруппировкиОтчета(Контекст, ИндексРаздела, Настройки2, Элемент2);
			
			ИндексироватьПоляГруппировкиОтчета(Контекст, ИндексГруппировки,
				Настройки, Элемент, Настройки2, Элемент2);
			
			ИндексироватьГруппировкиРазделаОтчета(Контекст, ИндексРаздела,
				Настройки, Элемент.Структура, Настройки2, Элемент2.Структура);
			
		КонецЕсли;
		
	КонецЦикла;
	
КонецПроцедуры

// Параметры:
//  Группировка - НастройкиКомпоновкиДанных
//              - ГруппировкаКомпоновкиДанных
//              - ГруппировкаТаблицыКомпоновкиДанных
//  Настройки - НастройкиКомпоновкиДанных
//  ПоляСортировки - Соответствие из КлючИЗначение:
//   * Ключ - ПолеКомпоновкиДанных
//   * Значение - НаправлениеСортировкиКомпоновкиДанных
//                 
//  Замещать - Булево
//
// Возвращаемое значение:
//  Соответствие
//
Функция ПоляСортировки(Группировка, Настройки, ПоляСортировки = Неопределено, Замещать = Истина)
	
	Если ПоляСортировки = Неопределено Тогда 
		ПоляСортировки = Новый Соответствие;
	КонецЕсли;
	
	ТипГруппировки = ТипЗнч(Группировка);
	
	Если ТипГруппировки <> Тип("НастройкиКомпоновкиДанных")
		И ТипГруппировки <> Тип("ГруппировкаКомпоновкиДанных")
		И ТипГруппировки <> Тип("ГруппировкаТаблицыКомпоновкиДанных") Тогда 
		
		Возврат ПоляСортировки;
	КонецЕсли;
	
	ЭлементыСортировки = Группировка.Порядок.Элементы;
	
	Для Каждого Элемент Из ЭлементыСортировки Цикл 
		
		Если Не Элемент.Использование Тогда 
			Продолжить;
		КонецЕсли;
		
		Если ТипЗнч(Элемент) = Тип("АвтоЭлементПорядкаКомпоновкиДанных")
			И ТипГруппировки <> Тип("НастройкиКомпоновкиДанных") Тогда 
			
			Для Каждого ЭлементПоля Из Группировка.ПоляГруппировки.Элементы Цикл
				Если ТипЗнч(ЭлементПоля) = Тип("ПолеГруппировкиКомпоновкиДанных")
				   И ПоляСортировки.Получить(ЭлементПоля.Поле) = Неопределено Тогда
					ПоляСортировки.Вставить(ЭлементПоля.Поле, НаправлениеСортировкиКомпоновкиДанных.Возр);
				КонецЕсли;
			КонецЦикла;
			
		ИначеЕсли ТипЗнч(Элемент) <> Тип("АвтоЭлементПорядкаКомпоновкиДанных")
			И (Замещать Или ПоляСортировки[Элемент.Поле] = Неопределено) Тогда 
			
			ПоляСортировки.Вставить(Элемент.Поле, Элемент.ТипУпорядочивания);
			
		КонецЕсли;
		
	КонецЦикла;
	
	Возврат ПоляСортировки;
	
КонецФункции

Функция ИндексГруппировкиОтчета(Контекст, ИндексРаздела, Настройки, Группировка)
	
	Контекст.ПорядокГруппировки = Контекст.ПорядокГруппировки + 1;
	
	ИндексГруппировки = Контекст.ИндексСтруктурыОтчета.Добавить();
	ЗаполнитьЗначенияСвойств(ИндексГруппировки, ИндексРаздела);
	
	ИндексГруппировки.ПорядокГруппировки = Контекст.ПорядокГруппировки;
	ИндексГруппировки.ИдентификаторГруппировки = Настройки.ПолучитьИдентификаторПоОбъекту(Группировка);
	ИндексГруппировки.ИмяГруппировки = Группировка.Имя;
	ИндексГруппировки.ПредставлениеГруппировки = ПредставлениеПолейГруппировки(Группировка);
	ИндексГруппировки.СодержитРодительскиеГруппировки = СодержитРодительскиеГруппировки(Группировка);
	ИндексГруппировки.СодержитДочерниеГруппировки = СодержитДочерниеГруппировки(Группировка);
	
	Возврат ИндексГруппировки;
	
КонецФункции

Функция СодержитРодительскиеГруппировки(Группировка)
	
	ТипРодителя = ТипЗнч(Группировка.Родитель);
	
	Возврат ТипРодителя = Тип("ГруппировкаКомпоновкиДанных")
		Или ТипРодителя = Тип("ГруппировкаТаблицыКомпоновкиДанных")
	
КонецФункции

Функция СодержитДочерниеГруппировки(Группировка)
	
	Для Каждого Элемент Из Группировка.Структура Цикл 
		
		ТипЭлемента = ТипЗнч(Элемент);
		
		Если ТипЭлемента <> Тип("ГруппировкаКомпоновкиДанных")
			И ТипЭлемента <> Тип("ГруппировкаТаблицыКомпоновкиДанных") Тогда 
			
			Продолжить;
		КонецЕсли;
		
		Если Элемент.Использование Тогда 
			Возврат Истина;
		КонецЕсли;
		
	КонецЦикла;
	
	Возврат Ложь;
	
КонецФункции

Процедура ИндексироватьПоляГруппировкиОтчета(Контекст, ИндексГруппировки,
			Настройки, Группировка, Настройки2, Группировка2)
	
	ИспользуемыеПоляГруппировки = Новый Соответствие;
	
	ИспользуетсяАвтоПоле = ИспользуетсяАвтоПоле(Группировка.Выбор);
	ИспользуемыеНастройки = ИспользуемыеНастройкиГруппировкиОтчета(Настройки, Группировка);
	
	ПоляГруппировки = Группировка2.ПоляГруппировки;
	
	Для Каждого Элемент Из ПоляГруппировки.Элементы Цикл 
		
		Если ТипЗнч(Элемент) <> Тип("ПолеГруппировкиКомпоновкиДанных")
			Или Не Элемент.Использование Тогда 
			
			Продолжить;
		КонецЕсли;
		
		ИспользуемыеПоляГруппировки.Вставить(Элемент.Поле, Элемент);
		
		Если ИспользуетсяАвтоПоле
			И Не ВариантыОтчетовСлужебныйКлиентСервер.ПолеСодержитсяВГруппировкеОтчета(Группировка.Выбор, Элемент.Поле)
			И Не ВариантыОтчетовСлужебныйКлиентСервер.ПолеСодержитсяВГруппировкеОтчета(ИспользуемыеНастройки.Выбор, Элемент.Поле) Тогда 
			
			ДобавитьПолеОтчетаВИндекс(Контекст,
				ИндексГруппировки, ПоляГруппировки, Элемент, ИспользуемыеПоляГруппировки);
			
		КонецЕсли;
		
	КонецЦикла;
	
	ИндексироватьВыбранныеПоляГруппировкиОтчета(Контекст,
		ИндексГруппировки, Настройки2, Группировка2, ИспользуемыеПоляГруппировки);
	
КонецПроцедуры

Функция ИспользуетсяАвтоПоле(Поля)
	
	Для Каждого Элемент Из Поля.Элементы Цикл 
		
		Если ТипЗнч(Элемент) = Тип("АвтоВыбранноеПолеКомпоновкиДанных")
			Или ТипЗнч(Элемент) = Тип("АвтоПолеГруппировкиКомпоновкиДанных") Тогда 
			
			Возврат Элемент.Использование;
		КонецЕсли;
		
	КонецЦикла;
	
	Возврат Ложь;
	
КонецФункции

Процедура ИндексироватьВыбранныеПоляГруппировкиОтчета(Контекст, ИндексГруппировки, Настройки,
			Группировка, ИспользуемыеПоляГруппировки, Поля = Неопределено, Родитель = Неопределено)
	
	Если Поля = Неопределено Тогда 
		Поля = Группировка.Выбор;
	КонецЕсли;
	
	Если Родитель = Неопределено Тогда 
		Родитель = Группировка.Выбор;
	КонецЕсли;
	
	Для Каждого Элемент Из Поля.Элементы Цикл 
		
		Если ТипЗнч(Элемент) = Тип("АвтоВыбранноеПолеКомпоновкиДанных") Тогда 
			
			ИндексироватьВыбранныеПоляНастроекОтчета(Контекст,
				ИндексГруппировки, Настройки, Группировка, ИспользуемыеПоляГруппировки);
			
		ИначеЕсли ТипЗнч(Элемент) = Тип("ГруппаВыбранныхПолейКомпоновкиДанных") Тогда 
			
			ИндексироватьВыбранныеПоляГруппировкиОтчета(Контекст, ИндексГруппировки, Настройки,
				Группировка, ИспользуемыеПоляГруппировки, Элемент, Родитель);
			
		ИначеЕсли РазрешеноИспользоватьПолеВГруппировке(Группировка, Элемент.Поле) Тогда 
			
			ДобавитьПолеОтчетаВИндекс(Контекст,
				ИндексГруппировки, Родитель, Элемент, ИспользуемыеПоляГруппировки);
			
		КонецЕсли;
		
	КонецЦикла;
	
КонецПроцедуры

Процедура ИндексироватьВыбранныеПоляНастроекОтчета(Контекст, ИндексГруппировки, Настройки,
			Группировка, ИспользуемыеПоляГруппировки, Поля = Неопределено, Родитель = Неопределено)
	
	ИспользуемыеНастройки = ИспользуемыеНастройкиГруппировкиОтчета(Настройки, Группировка);
	
	Если Поля = Неопределено Тогда 
		Поля = ИспользуемыеНастройки.Выбор;
	КонецЕсли;
	
	Если Родитель = Неопределено Тогда 
		Родитель = ИспользуемыеНастройки.Выбор;
	КонецЕсли;
	
	ПоляСортировки(Группировка, Настройки, Контекст.ПоляСортировки);
	
	Для Каждого Элемент Из Поля.Элементы Цикл 
		
		ТипЭлемента = ТипЗнч(Элемент);
		
		Если ТипЭлемента = Тип("ГруппаВыбранныхПолейКомпоновкиДанных") Тогда 
			
			ИндексироватьВыбранныеПоляНастроекОтчета(Контекст, ИндексГруппировки, Настройки,
				Группировка, ИспользуемыеПоляГруппировки, Элемент, Родитель);
			
		ИначеЕсли ТипЭлемента <> Тип("АвтоВыбранноеПолеКомпоновкиДанных")
			И РазрешеноИспользоватьПолеВГруппировке(Группировка, Элемент.Поле)
			И Не ВариантыОтчетовСлужебныйКлиентСервер.ПолеСодержитсяВГруппировкеОтчета(Группировка.Выбор, Элемент.Поле, Ложь) Тогда 
			
			ДобавитьПолеОтчетаВИндекс(Контекст, ИндексГруппировки, Родитель, Элемент, ИспользуемыеПоляГруппировки);
			
		КонецЕсли;
		
	КонецЦикла;
	
КонецПроцедуры

Функция РазрешеноИспользоватьПолеВГруппировке(Группировка, Поле)
	
	Элементы = Группировка.ПоляГруппировки.Элементы;
	ЭтоГруппировкаДетальныхЗаписей = (Элементы.Количество() = 0);
	
	Если ЭтоГруппировкаДетальныхЗаписей
		И (ВариантыОтчетовСлужебныйКлиентСервер.ПолеСодержитсяВГруппировкеОтчета(Группировка.Выбор, Поле)
		Или Не ВариантыОтчетовСлужебныйКлиентСервер.ПолеИспользуетсяВРодительскихГруппировкахОтчета(Группировка.Родитель, Поле)) Тогда 
		
		Возврат Истина;
	КонецЕсли;
	
	ДоступноеПоле = Группировка.Выбор.ДоступныеПоляВыбора.НайтиПоле(Поле);
	
	Если ДоступноеПоле = Неопределено Тогда 
		ДоступноеПоле = Группировка.ПоляГруппировки.ДоступныеПоляПолейГруппировок.НайтиПоле(Поле);
	КонецЕсли;
	
	Если ДоступноеПоле <> Неопределено
		И ДоступноеПоле.Ресурс Тогда 
		
		Возврат Истина;
	КонецЕсли;
	
	Для Каждого Элемент Из Элементы Цикл 
		
		Если ТипЗнч(Элемент) = Тип("ПолеГруппировкиКомпоновкиДанных")
			И Элемент.Использование
			И (Элемент.Поле = Поле
				Или СтрНайти(Строка(Элемент.Поле), Строка(Поле)) > 0
				Или СтрНайти(Строка(Поле), Строка(Элемент.Поле)) > 0) Тогда 
			
			Возврат Истина;
		КонецЕсли;
		
	КонецЦикла;
	
	Возврат Ложь;
	
КонецФункции

Функция ИспользуемыеНастройкиГруппировкиОтчета(Настройки, Группировка)
	
	Если ТипЗнч(Группировка.Родитель) = Тип("НастройкиКомпоновкиДанных") Тогда 
		Возврат Группировка.Родитель;
	КонецЕсли;
	
	Возврат Настройки;
	
КонецФункции

Процедура ДобавитьПолеОтчетаВИндекс(Контекст, ИндексГруппировки, Родитель, Поле, ИспользуемыеПоляГруппировки)
	
	Если Не Поле.Использование Тогда 
		Возврат;
	КонецЕсли;
	
	ОписаниеПоля = ОписаниеПоляОтчета(Родитель, Поле, ИспользуемыеПоляГруппировки);
	
	Если ОписаниеПоля.Ресурс
		И СтрНайти(ИндексГруппировки.ИдентификаторГруппировки, "/row/") > 0 Тогда 
		
		Возврат;
	КонецЕсли;
	
	Поиск = Новый Структура("ПорядокРаздела, ПорядокГруппировки, Поле");
	ЗаполнитьЗначенияСвойств(Поиск, ИндексГруппировки);
	Поиск.Поле = Поле.Поле;
	
	НайденныеИндексыПоля = Контекст.ИндексСтруктурыОтчета.НайтиСтроки(Поиск);
	
	Если НайденныеИндексыПоля.Количество() > 0 Тогда 
		
		ИндексПоля = НайденныеИндексыПоля[0];
		
	Иначе
		
		Контекст.ПорядокПоля = Контекст.ПорядокПоля + 1;
		
		ИндексПоля = Контекст.ИндексСтруктурыОтчета.Добавить();
		ЗаполнитьЗначенияСвойств(ИндексПоля, ИндексГруппировки);
		ИндексПоля.ПорядокПоля = Контекст.ПорядокПоля;
		
	КонецЕсли;
	
	ЗаполнитьЗначенияСвойств(ИндексПоля, ОписаниеПоля);
	
	ИндексПоля.ПредставлениеПоля = ВРег(ИндексПоля.ПредставлениеПоля);
	ИндексПоля.НаправлениеСортировки = Контекст.ПоляСортировки[Поле.Поле];
	ИндексПоля.ПолеСортируется = (ИндексПоля.НаправлениеСортировки <> Неопределено);
	
	Если ИндексПоля.ТипЗначения.СодержитТип(Тип("ТаблицаЗначений")) Тогда
		ИндексПоля.ТипЗначения = Новый ОписаниеТипов;
	КонецЕсли;
	
КонецПроцедуры

Функция ОписаниеПоляОтчета(Родитель, Поле, ИспользуемыеПоляГруппировки)
	
	ОписаниеПоля = Новый Структура;
	ОписаниеПоля.Вставить("Поле", Поле.Поле);
	ОписаниеПоля.Вставить("ИдентификаторПоля", Родитель.ПолучитьИдентификаторПоОбъекту(Поле));
	ОписаниеПоля.Вставить("ПредставлениеПоля", Строка(Поле.Поле));
	ОписаниеПоля.Вставить("ТипПоля", ТипЗнч(Поле));
	ОписаниеПоля.Вставить("ТипЗначения", Новый ОписаниеТипов("Неопределено"));
	ОписаниеПоля.Вставить("Ресурс", Ложь);
	
	ПолеГруппировки = ИспользуемыеПоляГруппировки[Поле.Поле];
	ТипГруппировки = ?(ПолеГруппировки = Неопределено, ТипГруппировкиКомпоновкиДанных.Элементы, ПолеГруппировки.ТипГруппировки);
	
	ОписаниеПоля.Вставить("ИспользуетсяВПоляхГруппировки", ПолеГруппировки <> Неопределено);
	ОписаниеПоля.Вставить("ТипГруппировки", ТипГруппировки);
	
	ДоступноеПоле = Неопределено;
	
	Если ОписаниеПоля.ТипПоля = Тип("ПолеГруппировкиКомпоновкиДанных") Тогда 
		
		ДоступноеПоле = Родитель.ДоступныеПоляПолейГруппировок.НайтиПоле(Поле.Поле);
		
	ИначеЕсли ОписаниеПоля.ТипПоля = Тип("ВыбранноеПолеКомпоновкиДанных") Тогда 
		
		ДоступноеПоле = Родитель.ДоступныеПоляВыбора.НайтиПоле(Поле.Поле);
		
	КонецЕсли;
	
	Если ДоступноеПоле <> Неопределено Тогда 
		
		ОписаниеПоля.ПредставлениеПоля = ДоступноеПоле.Заголовок;
		ОписаниеПоля.Ресурс = ДоступноеПоле.Ресурс;
		ОписаниеПоля.ТипЗначения = ДоступноеПоле.ТипЗначения;
		
	КонецЕсли;
	
	Если ОписаниеПоля.ТипПоля = Тип("ВыбранноеПолеКомпоновкиДанных")
		И ЗначениеЗаполнено(Поле.Заголовок) Тогда 
		
		ОписаниеПоля.ПредставлениеПоля = Поле.Заголовок;
	КонецЕсли;
	
	Возврат ОписаниеПоля;
	
КонецФункции

Процедура УдалитьНеидентифицированныеПоля(ИндексСтруктурыОтчета)
	
	НайденныеЗаписи = ИндексСтруктурыОтчета.НайтиСтроки(Новый Структура("ИдентификаторПоля", Неопределено));
	Для Каждого Запись Из НайденныеЗаписи Цикл 
		ИндексСтруктурыОтчета.Удалить(Запись);
	КонецЦикла;
	
КонецПроцедуры

Процедура УточнитьПорядокРазделов(ИндексСтруктурыОтчета)
	
	ИндексСтруктурыОтчета.Сортировать("ПорядокРаздела, ПорядокГруппировки, ПорядокПоля");
	
	Разделы = ИндексСтруктурыОтчета.Скопировать();
	Разделы.Свернуть("ПорядокРаздела");
	
	Поиск = Новый Структура("ПорядокРаздела");
	
	Для ПорядокРаздела = 1 По Разделы.Количество() Цикл 
		
		Поиск.ПорядокРаздела = Разделы[ПорядокРаздела - 1].ПорядокРаздела;
		НайденныеЗаписи = ИндексСтруктурыОтчета.НайтиСтроки(Поиск);
		
		Для Каждого Запись Из НайденныеЗаписи Цикл 
			Запись.ПорядокРаздела = ПорядокРаздела;
		КонецЦикла;
		
	КонецЦикла;
	
	ИндексСтруктурыОтчета.ЗаполнитьЗначения(Разделы.Количество(), "КоличествоРазделов");
	
КонецПроцедуры

Процедура ОпределитьРолиПолей(ИндексСтруктурыОтчета, РолиПолей)
	
	Для Каждого Запись Из ИндексСтруктурыОтчета Цикл 
		
		Запись.Период = (РолиПолей.Периоды[Запись.Поле] <> Неопределено);
		Запись.Измерение = (РолиПолей.Измерения[Запись.Поле] <> Неопределено);
		
	КонецЦикла;
	
КонецПроцедуры

Функция РолиПолейОтчета(АдресСхемы)
	
	РолиПолей = Новый Структура;
	РолиПолей.Вставить("Периоды", Новый Соответствие);
	РолиПолей.Вставить("Измерения", Новый Соответствие);
	РолиПолей.Вставить("Остатки", Новый Соответствие);
	
	Схема = ПолучитьИзВременногоХранилища(АдресСхемы);
	
	Для Каждого НаборДанных Из Схема.НаборыДанных Цикл 
		
		Для Каждого Поле Из НаборДанных.Поля Цикл 
			
			Если ТипЗнч(Поле) = Тип("ПапкаПолейНабораДанныхСхемыКомпоновкиДанных")
				Или ТипЗнч(Поле) = Тип("ВложенныйНаборДанныхСхемыКомпоновкиДанных") Тогда 
				
				Продолжить;
			КонецЕсли;
			
			Если Поле.Роль.НомерПериода > 0 Тогда 
				
				РолиПолей.Периоды.Вставить(Новый ПолеКомпоновкиДанных(Поле.Поле), ОписаниеРолиПоляОтчета(Поле.Роль));
				
			ИначеЕсли Поле.Роль.Измерение Тогда 
				
				РолиПолей.Измерения.Вставить(Новый ПолеКомпоновкиДанных(Поле.Поле), ОписаниеРолиПоляОтчета(Поле.Роль));
				
			ИначеЕсли Поле.Роль.Остаток Тогда 
				
				РолиПолей.Остатки.Вставить(Новый ПолеКомпоновкиДанных(Поле.Поле), ОписаниеРолиПоляОтчета(Поле.Роль));
				
			КонецЕсли;
			
		КонецЦикла;
		
	КонецЦикла;
	
	Возврат РолиПолей;
	
КонецФункции

Функция ОписаниеРолиПоляОтчета(Роль)
	
	ОписаниеРоли = Новый Структура("ВыражениеВидаСчета, ГруппаОстатка, ИгнорироватьЗначенияNULL, Измерение,
		|НомерПериода, Обязательное, Остаток, ПолеСчета, РеквизитИзмерения, РодительскоеИзмерение, Счет");
	
	ЗаполнитьЗначенияСвойств(ОписаниеРоли, Роль);
	
	ОписаниеРоли.Вставить("ТипБухгалтерскогоОстатка", Строка(Роль.ТипБухгалтерскогоОстатка));
	ОписаниеРоли.Вставить("РодительскоеИзмерение", Строка(Роль.РодительскоеИзмерение));
	ОписаниеРоли.Вставить("ТипПериода", Строка(Роль.ТипПериода));
	
	Возврат ОписаниеРоли;
	
КонецФункции

Процедура ОпределитьПоляФормулы(АдресСхемы, Настройки, ИндексСтруктурыОтчета)
	
	Для Каждого Запись Из ИндексСтруктурыОтчета Цикл 
		Запись.ЭтоФормула = ЭтоПользовательскоеПоле(Настройки.ПользовательскиеПоля, Запись.Поле);
	КонецЦикла;
	
	Если Не ЭтоАдресВременногоХранилища(АдресСхемы) Тогда 
		Возврат;
	КонецЕсли;
	
	Схема = ПолучитьИзВременногоХранилища(АдресСхемы);
	
	Если ТипЗнч(Схема) <> Тип("СхемаКомпоновкиДанных") Тогда 
		Возврат;
	КонецЕсли;
	
	НайденныеЗаписи = ИндексСтруктурыОтчета.НайтиСтроки(Новый Структура("ЭтоФормула", Ложь));
	ВычисляемыеПоля = Схема.ВычисляемыеПоля;
	
	Для Каждого Запись Из НайденныеЗаписи Цикл 
		Запись.ЭтоФормула = ВычисляемыеПоля.Найти(Строка(Запись.Поле)) <> Неопределено;
	КонецЦикла;
	
КонецПроцедуры

Функция ЭтоПользовательскоеПоле(ПользовательскиеПоля, Поле)
	
	Для Каждого Элемент Из ПользовательскиеПоля.Элементы Цикл 
		
		Если Элемент.ПутьКДанным = Строка(Поле) Тогда 
			Возврат Истина;
		КонецЕсли;
		
	КонецЦикла;
	
	Возврат Ложь;
	
КонецФункции

Процедура УстановитьИдентификаторыИндексаСтруктурыОтчета(ИндексСтруктурыОтчета)
	
	Для Каждого Индекс Из ИндексСтруктурыОтчета Цикл 
		Индекс.ИдентификаторИндекса = Новый УникальныйИдентификатор();
	КонецЦикла;
	
	ИндексСтруктурыОтчета.Индексы.Добавить("ИдентификаторИндекса");
	
КонецПроцедуры

Процедура ОпределитьДоступныеДействияПолейОтчета(ИндексСтруктурыОтчета)
	
	Разделы = ИндексСтруктурыОтчета.Скопировать();
	Разделы.Свернуть("ПорядокРаздела");
	ПорядокРазделов = Разделы.ВыгрузитьКолонку("ПорядокРаздела");
	
	Для Каждого ПорядокРаздела Из ПорядокРазделов Цикл 
		
		ОпределитьДоступныеДействияПолейРазделаОтчета(ИндексСтруктурыОтчета, ПорядокРаздела);
		ОпределитьДоступныеДействияПолейРазделаОтчета(ИндексСтруктурыОтчета, ПорядокРаздела, Истина);
		
	КонецЦикла;
	
КонецПроцедуры

Процедура ОпределитьДоступныеДействияПолейРазделаОтчета(ИндексСтруктурыОтчета, ПорядокРаздела, ЭтоРесурс = Ложь)
	
	ПоискПолейРаздела = Новый Структура("ПорядокРаздела, Ресурс", ПорядокРаздела, ЭтоРесурс);
	ПоляГруппировок = ИндексСтруктурыОтчета.Скопировать(ПоискПолейРаздела);
	
	ПоискПолейГруппировки = Новый Структура("ПорядокГруппировки");
	
	Группировки = ПоляГруппировок.Скопировать();
	Группировки.Свернуть("ПорядокГруппировки");
	ПорядокГруппировок = Группировки.ВыгрузитьКолонку("ПорядокГруппировки");
	ПоляГруппировкиВыше = Неопределено;
	
	Для Каждого ПорядокГруппировки Из ПорядокГруппировок Цикл 
		
		ПоискПолейГруппировки.ПорядокГруппировки = ПорядокГруппировки;
		ПоляГруппировки = ПоляГруппировок.Скопировать(ПоискПолейГруппировки);
		ПоляГруппировки.Сортировать("ПорядокПоля");
		
		ПоляГруппировкиНиже = Неопределено;
		Индекс = ПорядокГруппировок.Найти(ПорядокГруппировки);
		Если Индекс + 1 < ПорядокГруппировок.Количество() Тогда
			ПоискПолейГруппировки.ПорядокГруппировки = ПорядокГруппировок[Индекс + 1];
			ПоляГруппировкиНиже = ПоляГруппировок.Скопировать(ПоискПолейГруппировки);
		КонецЕсли;
		
		Для Каждого ПолеГруппировки Из ПоляГруппировки Цикл 
			
			ЭтоПолеГруппировкиКолонки = СтрНайти(ПолеГруппировки.ИдентификаторГруппировки, "/column/") > 0
				И ПолеГруппировки.ИспользуетсяВПоляхГруппировки;
			
			Индекс = ИндексСтруктурыОтчета.Найти(ПолеГруппировки.ИдентификаторИндекса, "ИдентификаторИндекса");
			Индекс.СгруппироватьПоВыбранномуПолю = Не ЭтоПолеГруппировкиКолонки;
			Индекс.ВставитьПолеСлева = Не ЭтоПолеГруппировкиКолонки;
			Индекс.ВставитьПолеСправа = Не ЭтоПолеГруппировкиКолонки;
			Индекс.ВставитьГруппировкуВыше = Не ЭтоПолеГруппировкиКолонки И Не ЭтоРесурс;
			Индекс.ВставитьГруппировкуНиже = Не ЭтоПолеГруппировкиКолонки И Не ЭтоРесурс;
			
			Индекс.ПереместитьПолеВыше = Не ЭтоПолеГруппировкиКолонки
				И ПорядокРаздела = 1
				И Не ЭтоРесурс
				И Индекс.СодержитРодительскиеГруппировки
				И ПоляГруппировкиВыше <> Неопределено
				И ПоляГруппировкиВыше.Найти(Не ПолеГруппировки.Период, "Период") = Неопределено;
			
			Индекс.ПереместитьПолеНиже = Не ЭтоПолеГруппировкиКолонки
				И ПорядокРаздела = 1
				И Не ЭтоРесурс
				И Индекс.СодержитДочерниеГруппировки
				И ПоляГруппировкиНиже <> Неопределено
				И ПоляГруппировкиНиже.Найти(Не ПолеГруппировки.Период, "Период") = Неопределено;
			
			Если Не ЭтоПолеГруппировкиКолонки
				И ПоляГруппировки.Индекс(ПолеГруппировки) > 0 Тогда 
				
				Индекс.ПереместитьПолеВлево = Истина;
			КонецЕсли;
			
			Если Не ЭтоПолеГруппировкиКолонки
				И ПоляГруппировки.Индекс(ПолеГруппировки) < ПоляГруппировки.Количество() - 1 Тогда 
				
				Индекс.ПереместитьПолеВправо = Истина;
			КонецЕсли;
			
			Индекс.СкрытьПоле = Не ЭтоПолеГруппировкиКолонки;
			Индекс.ПереименоватьПоле = Не ЭтоПолеГруппировкиКолонки;
			Индекс.ОформитьЕще = Не ЭтоПолеГруппировкиКолонки;
			
		КонецЦикла;
		
		ПоляГруппировкиВыше = ПоляГруппировки;
	КонецЦикла;
	
КонецПроцедуры

Функция ИндексПолейСтруктурыОтчета(ИндексСтруктурыОтчета)
	
	ИндексПолей = Новый Соответствие;
	
	Разделы = ИндексСтруктурыОтчета.Скопировать();
	Разделы.Свернуть("ПорядокРаздела");
	
	ПорядокРазделов = Разделы.ВыгрузитьКолонку("ПорядокРаздела");
	
	ПоискГруппировок = Новый Структура("ПорядокРаздела");
	ПоискПоля = Новый Структура("ПорядокРаздела, ПорядокГруппировки");
	
	Для Каждого ПорядокРаздела Из ПорядокРазделов Цикл 
		
		ПоискГруппировок.ПорядокРаздела = ПорядокРаздела;
		Группировки = ИндексСтруктурыОтчета.Скопировать(ПоискГруппировок);
		Группировки.Свернуть("ПорядокГруппировки");
		
		ПорядокГруппировок = Группировки.ВыгрузитьКолонку("ПорядокГруппировки");
		
		ИндексПолейРаздела = ИндексПолей[ПорядокРаздела];
		Если ИндексПолейРаздела = Неопределено Тогда 
			ИндексПолейРаздела = Новый Соответствие;
		КонецЕсли;
		
		Для Каждого ПорядокГруппировки Из ПорядокГруппировок Цикл 
			
			ПоискПоля.ПорядокРаздела = ПорядокРаздела;
			ПоискПоля.ПорядокГруппировки = ПорядокГруппировки;
			ПоляГруппировки = ИндексСтруктурыОтчета.НайтиСтроки(ПоискПоля);
			
			ИндексПолейГруппировки = ИндексПолейРаздела[ПорядокГруппировки];
			Если ИндексПолейГруппировки = Неопределено Тогда 
				ИндексПолейГруппировки = Новый Соответствие;
			КонецЕсли;
			
			Для Каждого ПолеГруппировки Из ПоляГруппировки Цикл 
				
				СвойстваПоля = СтандартныеСвойстваПоляОтчета();
				ЗаполнитьЗначенияСвойств(СвойстваПоля, ПолеГруппировки);
				
				ИндексПолейГруппировки.Вставить(ПолеГруппировки.Поле, СвойстваПоля);
				
			КонецЦикла;
			
			ИндексПолейРаздела.Вставить(ПорядокГруппировки, ИндексПолейГруппировки);
			
		КонецЦикла;
		
		ИндексПолей.Вставить(ПорядокРаздела, ИндексПолейРаздела);
		
	КонецЦикла;
	
	Возврат ИндексПолей;
	
КонецФункции

Функция ОсновныеПоляОтчета(Форма)
	
	ОсновныеПоля = Новый Массив;
	
	ОтчетыПереопределяемый.ПриОпределенииОсновныхПолей(Форма, ОсновныеПоля);
	
	// Локальное переопределение для отчета.
	Если Форма.НастройкиОтчета.События.ПриОпределенииОсновныхПолей Тогда 
		
		Отчет = ОтчетыСервер.ОтчетОбъект(Форма.НастройкиОтчета.ПолноеИмя);
		Отчет.ПриОпределенииОсновныхПолей(Форма, ОсновныеПоля);
		
	КонецЕсли;
	
	Возврат ОсновныеПоля;
	
КонецФункции

Функция МакетыКомпоновкиДанныхОписаны(АдресСхемы)
	
	Схема = ПолучитьИзВременногоХранилища(АдресСхемы);
	
	Если ТипЗнч(Схема) <> Тип("СхемаКомпоновкиДанных") Тогда 
		Возврат Ложь;
	КонецЕсли;
	
	Возврат Схема.Макеты.Количество() > 0
		Или Схема.МакетыЗаголовковГруппировок.Количество() > 0
		Или Схема.МакетыГруппировок.Количество() > 0
		Или Схема.МакетыПолей.Количество() > 0
		Или Схема.МакетыПолейИтога.Количество() > 0;
	
КонецФункции

Процедура ЗаполнитьСвойстваМакетовЗаголовковОтчета(АдресСхемы, ИндексСтруктурыОтчета)
	
	Схема = ПолучитьИзВременногоХранилища(АдресСхемы);
	
	МакетыПоТипам = Новый Массив;
	МакетыПоТипам.Добавить(Схема.МакетыЗаголовковГруппировок);
	МакетыПоТипам.Добавить(Схема.МакетыГруппировок);
	
	Для Каждого МакетыПоТипу Из МакетыПоТипам Цикл 
	
		Для Каждого Макет Из МакетыПоТипу Цикл 
			
			ИндексГруппировки = ИндексСтруктурыОтчета.Найти(Макет.ИмяГруппировки, "ИмяГруппировки");
			
			Если ИндексГруппировки = Неопределено Тогда 
				Продолжить;
			КонецЕсли;
			
			ОписаниеМакета = Схема.Макеты.Найти(Макет.Макет);
			
			Если ТипЗнч(ОписаниеМакета.Макет) <> Тип("МакетОбластиКомпоновкиДанных") Тогда 
				Продолжить;
			КонецЕсли;
			
			Для Каждого Строка Из ОписаниеМакета.Макет Цикл 
				
				Для Каждого Ячейка Из Строка.Ячейки Цикл 
					
					Если Ячейка.Элементы.Количество() > 0 Тогда 
						ИндексГруппировки.Текст = Ячейка.Элементы[0].Значение;
					КонецЕсли;
					
				КонецЦикла;
				
			КонецЦикла;
			
		КонецЦикла;
		
	КонецЦикла;
	
КонецПроцедуры

// Возвращаемое значение:
//  ТаблицаЗначений:
//    * ПорядокРаздела - Число
//    * КоличествоРазделов - Число
//    * ПорядокГруппировки - Число
//    * ПорядокПоля - Число
//    * ИдентификаторНастроек - ИдентификаторКомпоновкиДанных
//    * ИдентификаторРаздела - ИдентификаторКомпоновкиДанных
//    * ИдентификаторГруппировки - ИдентификаторКомпоновкиДанных
//    * ИдентификаторПоля - ИдентификаторКомпоновкиДанных
//    * Поле - ПолеКомпоновкиДанных
//    * ТипПоля - Тип
//    * ИспользуетсяВПоляхГруппировки - Булево
//    * ТипГруппировки - ТипГруппировкиКомпоновкиДанных
//    * ИмяГруппировки - Строка
//    * ПредставлениеГруппировки - Строка
//    * ПредставлениеПоля - Строка
//    * Текст - Строка
//    * Период - Булево
//    * Измерение - Булево
//    * Ресурс - Булево
//    * ЭтоФормула - Булево
//    * ТипЗначения - Тип
//    * ПолеСортируется - Булево
//    * НаправлениеСортировки - НаправлениеСортировкиКомпоновкиДанных
//    * СгруппироватьПоВыбранномуПолю - Булево
//    * ВставитьПолеСлева - Булево
//    * ВставитьПолеСправа - Булево
//    * ВставитьГруппировкуВыше - Булево
//    * ВставитьГруппировкуНиже - Булево
//    * ПереместитьПолеВлево - Булево
//    * ПереместитьПолеВправо - Булево
//    * ПереместитьПолеВыше - Булево
//    * ПереместитьПолеНиже - Булево
//    * СкрытьПоле - Булево
//    * ПереименоватьПоле - Булево
//    * ОформитьОтрицательные - Булево
//    * ОформитьПоложительные - Булево
//    * ОформитьЕще - Булево
//    * СодержитРодительскиеГруппировки - Булево
//    * СодержитДочерниеГруппировки - Булево
//    * ИдентификаторИндекса - УникальныйИдентификатор
// 
Функция НовыйИндексСтруктурыОтчета() Экспорт 
	
	ОписаниеЧисла = Новый ОписаниеТипов("Число");
	ОписаниеСтроки = Новый ОписаниеТипов("Строка");
	ОписаниеПризнака = Новый ОписаниеТипов("Булево");
	ОписаниеПоля = Новый ОписаниеТипов("ПолеКомпоновкиДанных");
	ОписаниеТипов = Новый ОписаниеТипов("ОписаниеТипов");
	ОписаниеТипа = Новый ОписаниеТипов("Тип");
	ОписаниеИдентификатора = Новый ОписаниеТипов("УникальныйИдентификатор");
	ОписаниеТипаГруппировки = Новый ОписаниеТипов("ТипГруппировкиКомпоновкиДанных");
	
	Индекс = Новый ТаблицаЗначений;
	Индекс.Колонки.Добавить("ПорядокРаздела", ОписаниеЧисла);
	Индекс.Колонки.Добавить("КоличествоРазделов", ОписаниеЧисла);
	Индекс.Колонки.Добавить("ПорядокГруппировки", ОписаниеЧисла);
	Индекс.Колонки.Добавить("ПорядокПоля", ОписаниеЧисла);
	
	Индекс.Колонки.Добавить("ИдентификаторНастроек");
	Индекс.Колонки.Добавить("ИдентификаторРаздела");
	Индекс.Колонки.Добавить("ИдентификаторГруппировки");
	Индекс.Колонки.Добавить("ИдентификаторПоля");
	
	Индекс.Колонки.Добавить("Поле", ОписаниеПоля);
	Индекс.Колонки.Добавить("ТипПоля", ОписаниеТипа);
	
	Индекс.Колонки.Добавить("ИспользуетсяВПоляхГруппировки", ОписаниеПризнака);
	Индекс.Колонки.Добавить("ТипГруппировки", ОписаниеТипаГруппировки);
	
	Индекс.Колонки.Добавить("ИмяГруппировки", ОписаниеСтроки);
	Индекс.Колонки.Добавить("ПредставлениеГруппировки", ОписаниеСтроки);
	Индекс.Колонки.Добавить("ПредставлениеПоля", ОписаниеСтроки);
	Индекс.Колонки.Добавить("Текст", ОписаниеСтроки);
	
	Индекс.Колонки.Добавить("Период", ОписаниеПризнака);
	Индекс.Колонки.Добавить("Измерение", ОписаниеПризнака);
	Индекс.Колонки.Добавить("Ресурс", ОписаниеПризнака);
	Индекс.Колонки.Добавить("ЭтоФормула", ОписаниеПризнака);
	
	Индекс.Колонки.Добавить("ТипЗначения", ОписаниеТипов);
	Индекс.Колонки.Добавить("ПолеСортируется", ОписаниеПризнака);
	Индекс.Колонки.Добавить("НаправлениеСортировки");
	
	Индекс.Колонки.Добавить("СгруппироватьПоВыбранномуПолю", ОписаниеПризнака);
	
	Индекс.Колонки.Добавить("ВставитьПолеСлева", ОписаниеПризнака);
	Индекс.Колонки.Добавить("ВставитьПолеСправа", ОписаниеПризнака);
	Индекс.Колонки.Добавить("ВставитьГруппировкуВыше", ОписаниеПризнака);
	Индекс.Колонки.Добавить("ВставитьГруппировкуНиже", ОписаниеПризнака);
	
	Индекс.Колонки.Добавить("ПереместитьПолеВлево", ОписаниеПризнака);
	Индекс.Колонки.Добавить("ПереместитьПолеВправо", ОписаниеПризнака);
	Индекс.Колонки.Добавить("ПереместитьПолеВыше", ОписаниеПризнака);
	Индекс.Колонки.Добавить("ПереместитьПолеНиже", ОписаниеПризнака);
	
	Индекс.Колонки.Добавить("СкрытьПоле", ОписаниеПризнака);
	Индекс.Колонки.Добавить("ПереименоватьПоле", ОписаниеПризнака);
	
	Индекс.Колонки.Добавить("ОформитьОтрицательные", ОписаниеПризнака);
	Индекс.Колонки.Добавить("ОформитьПоложительные", ОписаниеПризнака);
	Индекс.Колонки.Добавить("ОформитьЕще", ОписаниеПризнака);
	
	Индекс.Колонки.Добавить("СодержитРодительскиеГруппировки", ОписаниеПризнака);
	Индекс.Колонки.Добавить("СодержитДочерниеГруппировки", ОписаниеПризнака);
	
	Индекс.Колонки.Добавить("ИдентификаторИндекса", ОписаниеИдентификатора);
	
	Возврат Индекс;
	
КонецФункции

Функция СтандартныеСвойстваПоляОтчета()
	
	Индекс = Новый Структура;
	Индекс.Вставить("ПорядокПоля", 0);
	Индекс.Вставить("ИдентификаторПоля", Неопределено);
	Индекс.Вставить("ПредставлениеПоля", "");
	
	Индекс.Вставить("ПолеСортируется", Ложь);
	Индекс.Вставить("НаправлениеСортировки", Неопределено);
	
	Индекс.Вставить("Ресурс", Ложь);
	Индекс.Вставить("ТипЗначения", Неопределено);
	Индекс.Вставить("ТипПоля", Неопределено);
	
	Индекс.Вставить("ИдентификаторНастроек", Неопределено);
	Индекс.Вставить("ИдентификаторРаздела", Неопределено);
	Индекс.Вставить("ИдентификаторГруппировки", Неопределено);
	
	Индекс.Вставить("ИдентификаторИндекса", Неопределено);
	
	Возврат Индекс;
	
КонецФункции

#КонецОбласти

#Область ИнициализацияСвойствЗаголовковТаблиц

Процедура ОпределитьИерархиюЗаголовковОтчета(РазрезСвойствЗаголовков, Заголовки)
	
	РазрезСвойствЗаголовков.Свернуть("Верх, Лево, Низ, Право, Имя, Расшифровка");
	РазрезСвойствЗаголовков.Сортировать("Верх, Лево");
	РазрезСвойствЗаголовков.Индексы.Добавить("Верх, Низ, Лево");
	
	Для Каждого Запись Из РазрезСвойствЗаголовков Цикл 
		
		Если Запись.Расшифровка <> Неопределено Тогда 
			Продолжить;
		КонецЕсли;
		
		Верх = Запись.Низ + 1;
		НайденныеОбласти = РазрезСвойствЗаголовков.НайтиСтроки(Новый Структура("Верх, Лево", Верх, Запись.Лево));
		
		Пока НайденныеОбласти.Количество() > 0 Цикл 
			
			СвойстваОбласти = Заголовки[Запись.Имя];
			СвойстваОбласти.КоличествоДочернихЗаголовков = СвойстваОбласти.КоличествоДочернихЗаголовков + 1;
			
			Верх = Верх + 1;
			НайденныеОбласти = РазрезСвойствЗаголовков.НайтиСтроки(Новый Структура("Верх, Лево", Верх, Запись.Лево));
			
		КонецЦикла;
		
		Низ = Запись.Верх - 1;
		НайденныеОбласти = РазрезСвойствЗаголовков.НайтиСтроки(Новый Структура("Низ, Лево", Низ, Запись.Лево));
		
		Пока НайденныеОбласти.Количество() > 0 Цикл 
			
			СвойстваОбласти = Заголовки[Запись.Имя];
			СвойстваОбласти.КоличествоРодительскихЗаголовков = СвойстваОбласти.КоличествоРодительскихЗаголовков + 1;
			
			Низ = Низ - 1;
			НайденныеОбласти = РазрезСвойствЗаголовков.НайтиСтроки(Новый Структура("Низ, Лево", Низ, Запись.Лево));
			
		КонецЦикла;
		
	КонецЦикла;
	
КонецПроцедуры

Функция ГраницыРазделовОтчета(РезультатОтчета, РазрезСвойствЗаголовков)
	
	Границы = Новый СписокЗначений;
	
	ВерхниеГраницы = РазрезСвойствЗаголовков.Скопировать();
	ВерхниеГраницы.Свернуть("Верх");
	ВерхниеГраницы.Сортировать("Верх");
	
	Для Каждого Запись Из ВерхниеГраницы Цикл 
		
		Индекс = ВерхниеГраницы.Индекс(Запись);
		
		Если Индекс = 0 Тогда 
			Продолжить;
		КонецЕсли;
		
		Если (Запись.Верх - ВерхниеГраницы[Индекс - 1].Верх) > 1 Тогда 
			Границы.Добавить(Макс(0, Запись.Верх - 1));
		КонецЕсли;
		
	КонецЦикла;
	
	Границы.Добавить(РезультатОтчета.ВысотаТаблицы);
	
	Возврат Границы;
	
КонецФункции

Процедура ДополнитьСвойстваЗаголовковОтчета(Форма, РезультатОтчета, Заголовки, РазрезСвойствЗаголовков, ИндексСтруктурыОтчета, ГраницыРазделов)
	
	ПорядокРаздела = 1;
	ГраницаТекущегоРаздела = 0;
	ОбработанныеПоля = Новый Соответствие;
	
	Для Каждого Граница Из ГраницыРазделов Цикл 
		
		Для Каждого Запись Из РазрезСвойствЗаголовков Цикл 
			
			СвойстваЗаголовка = Заголовки[Запись.Имя];
			
			Если СвойстваЗаголовка.Верх >= ГраницаТекущегоРаздела
				И СвойстваЗаголовка.Верх <= Граница.Значение Тогда 
				
				ИндексПоля = ИндексПоляПоСвойствамЗаголовка(
					Форма, СвойстваЗаголовка, ИндексСтруктурыОтчета, ПорядокРаздела, ОбработанныеПоля);
				
				Если ИндексПоля = Неопределено Тогда 
					Продолжить;
				КонецЕсли;
				
				ЗаполнитьЗначенияСвойств(СвойстваЗаголовка, ИндексПоля,, "Текст");
				
				Если ЗначениеЗаполнено(ИндексПоля.Текст) Тогда 
					СвойстваЗаголовка.Текст = ИндексПоля.Текст;
				КонецЕсли;
				
				ЭтоЧисло = СвойстваЗаголовка.ТипЗначения.СодержитТип(Тип("Число"));
				СвойстваЗаголовка.ОформитьОтрицательные = ЭтоЧисло;
				СвойстваЗаголовка.ОформитьПоложительные = ЭтоЧисло;
				
				Если Форма.ПолучитьТекущийРежимОтображенияРезультата() = РежимОтображенияРезультатаОтчета.Обычный Тогда
					ВставитьИндикаторСортировки(ИндексПоля, СвойстваЗаголовка, РезультатОтчета.Область(Запись.Имя));
				КонецЕсли;
				
			КонецЕсли;
			
		КонецЦикла;
		
		ПорядокРаздела = ПорядокРаздела + 1;
		ГраницаТекущегоРаздела = Граница.Значение;
		
	КонецЦикла;
	
КонецПроцедуры

Функция ИндексПоляПоСвойствамЗаголовка(Форма, СвойстваЗаголовка, ИндексСтруктурыОтчета, ПорядокРаздела, ОбработанныеПоля)
	
	Поиск = Новый Структура("ПорядокРаздела, ПредставлениеПоля", ПорядокРаздела, ВРег(СвойстваЗаголовка.Текст));
	ИндексПоля = ИндексПоляПоПредставлению(ИндексСтруктурыОтчета, Поиск, ОбработанныеПоля);
	
	Если ИндексПоля = Неопределено Тогда 
		ИндексПоля = ИндексПоляПоРасшифровке(Форма, СвойстваЗаголовка.Расшифровка, ИндексСтруктурыОтчета, Поиск, ОбработанныеПоля);
	КонецЕсли;
	
	Если ИндексПоля <> Неопределено Тогда 
		Возврат ИндексПоля;
	КонецЕсли;
	
	Поиск = Новый Структура("ПорядокРаздела, Текст", ПорядокРаздела, СвойстваЗаголовка.Текст);
	НайденныеЗаписи = ИндексСтруктурыОтчета.НайтиСтроки(Поиск);
	
	Если НайденныеЗаписи.Количество() > 0 Тогда 
		ИндексПоля = НайденныеЗаписи[0];
	КонецЕсли;
	
	Возврат ИндексПоля;
	
КонецФункции

Функция ИндексПоляПоРасшифровке(Форма, Расшифровка, ИндексСтруктурыОтчета, Поиск, ОбработанныеПоля)
	
	Если ТипЗнч(Расшифровка) <> Тип("ИдентификаторРасшифровкиКомпоновкиДанных") Тогда 
		Возврат Неопределено;
	КонецЕсли;
	
	Данные = ДанныеЭлементаРасшифровки(Форма, Расшифровка);
	
	Если Данные = Неопределено Тогда 
		Возврат Неопределено;
	КонецЕсли;
	
	ПоискПоПолю = Новый Структура;
	ПоискПоПолю.Вставить("ПорядокРаздела", Поиск.ПорядокРаздела);
	ПоискПоПолю.Вставить("Поле", Новый ПолеКомпоновкиДанных(Данные.Поле));
	
	НайденныеПоля = ИндексСтруктурыОтчета.НайтиСтроки(ПоискПоПолю);
	
	Если НайденныеПоля.Количество() > 0 Тогда 
		Возврат НайденныеПоля[0];
	КонецЕсли;
	
	Поиск.ПредставлениеПоля = ВРег(Данные.Поле);
	
	Возврат ИндексПоляПоПредставлению(ИндексСтруктурыОтчета, Поиск, ОбработанныеПоля);
	
КонецФункции

Функция ИндексПоляПоПредставлению(ИндексСтруктурыОтчета, Поиск, ОбработанныеПоля)
	
	ПодходящееПоле = ПодходящееПоле(ИндексСтруктурыОтчета, Поиск, ОбработанныеПоля);
	
	Если ПодходящееПоле <> Неопределено Тогда 
		Возврат ПодходящееПоле;
	КонецЕсли;
	
	ОбластьВладельцаСРеквизитами = СтрНайти(Поиск.ПредставлениеПоля, ",") > 0;
	
	Если ОбластьВладельцаСРеквизитами Тогда 
		Поиск.ПредставлениеПоля = СтрРазделить(Поиск.ПредставлениеПоля, ",")[0];
	КонецЕсли;
	
	ПодходящееПоле = ПодходящееПоле(ИндексСтруктурыОтчета, Поиск, ОбработанныеПоля);
	
	Если ПодходящееПоле <> Неопределено Тогда 
		Возврат ПодходящееПоле;
	КонецЕсли;
	
	ОписаниеЗаголовка = СтрРазделить(Поиск.ПредставлениеПоля, ".");
	
	ПоискРаздела = Новый Структура("ПорядокРаздела", Поиск.ПорядокРаздела);
	НайденныеПоля = ИндексСтруктурыОтчета.НайтиСтроки(ПоискРаздела);
	
	Для Каждого ИндексПоля Из НайденныеПоля Цикл 
		
		ОписаниеПредставления = СтрРазделить(ИндексПоля.ПредставлениеПоля, ".");
		
		КоличествоСовпадений = 0;
		
		Для Каждого Фрагмент Из ОписаниеЗаголовка Цикл 
			
			НормализованныйФрагмент = СокрЛП(Фрагмент);
			
			Если ОписаниеПредставления.Найти(НормализованныйФрагмент) <> Неопределено Тогда 
				КоличествоСовпадений = КоличествоСовпадений + 1;
			КонецЕсли;
			
		КонецЦикла;
		
		Если ОбластьВладельцаСРеквизитами
			И КоличествоСовпадений = ОписаниеПредставления.Количество()
			Или Не ОбластьВладельцаСРеквизитами
			И КоличествоСовпадений = ОписаниеЗаголовка.Количество() Тогда 
			
			Возврат ИндексПоля;
		КонецЕсли;
		
	КонецЦикла;
	
	Возврат Неопределено;
	
КонецФункции

Функция ПодходящееПоле(ИндексСтруктурыОтчета, Поиск, ОбработанныеПоля)
	
	НайденныеПоля = ИндексСтруктурыОтчета.НайтиСтроки(Поиск);
	
	Возврат ИндексПоляНеобработанный(
		ИндексСтруктурыОтчета, Поиск.ПредставлениеПоля, НайденныеПоля, ОбработанныеПоля);
	
КонецФункции

Функция ИндексПоляНеобработанный(ИндексСтруктурыОтчета, ПредставлениеПоля, НайденныеПоля, ОбработанныеПоля)
	
	Если НайденныеПоля.Количество() = 0 Тогда 
		Возврат Неопределено;
	КонецЕсли;
	
	Если НайденныеПоля.Количество() = 1 Тогда 
		Возврат НайденныеПоля[0];
	КонецЕсли;
	
	ОбработанныеИндексы = ОбработанныеПоля[ПредставлениеПоля];
	
	Если ОбработанныеИндексы = Неопределено Тогда 
		
		ПодходящееПоле = НайденныеПоля[0];
		
		ОбработанныеИндексы = Новый Соответствие;
		ОбработанныеИндексы.Вставить(ИндексСтруктурыОтчета.Индекс(ПодходящееПоле), ПодходящееПоле);
		
		ОбработанныеПоля.Вставить(ПредставлениеПоля, ОбработанныеИндексы);
		
		Возврат ПодходящееПоле;
		
	КонецЕсли;
	
	ПодходящееПоле = Неопределено;
	
	Для Каждого НайденноеПоле Из НайденныеПоля Цикл 
		
		ИндексПоля = ИндексСтруктурыОтчета.Индекс(НайденноеПоле);
		
		Если ОбработанныеИндексы[ИндексПоля] = Неопределено Тогда 
			
			ПодходящееПоле = НайденноеПоле;
			Прервать;
			
		КонецЕсли;
		
	КонецЦикла;
	
	Если ПодходящееПоле = Неопределено Тогда 
		Возврат НайденныеПоля[0];
	КонецЕсли;
	
	ОбработанныеИндексы.Вставить(ИндексПоля, ПодходящееПоле);
	ОбработанныеПоля.Вставить(ПредставлениеПоля, ОбработанныеИндексы);
	
	Возврат ПодходящееПоле;
	
КонецФункции

Процедура ВставитьИндикаторСортировки(ИндексПоля, СвойстваЗаголовка, Ячейка)
	
	Если Не ИндексПоля.ПолеСортируется Тогда 
		Возврат;
	КонецЕсли;
	
	МинимальнаяШиринаКолонкиДляВыводаИндикатора = 5;
	
	Если Ячейка.ШиринаКолонки > 0
		И Ячейка.ШиринаКолонки <= МинимальнаяШиринаКолонкиДляВыводаИндикатора Тогда 
		
		Возврат;
	КонецЕсли;
	
	Если СвойстваЗаголовка.ПорядокРаздела <> 1 Тогда
		Возврат;
	КонецЕсли;
	
	Если ИндексПоля.НаправлениеСортировки = НаправлениеСортировкиКомпоновкиДанных.Возр Тогда 
		
		СвойстваЗаголовка.СортироватьПоВозрастанию = Ложь;
		Ячейка.Картинка = БиблиотекаКартинок.СортироватьСтрокиПоВозрастанию;
		
	ИначеЕсли ИндексПоля.НаправлениеСортировки = НаправлениеСортировкиКомпоновкиДанных.Убыв Тогда 
		
		СвойстваЗаголовка.СортироватьПоУбыванию = Ложь;
		Ячейка.Картинка = БиблиотекаКартинок.СортироватьСтрокиПоУбыванию;
		
	КонецЕсли;
	
	Ячейка.РазмерКартинки = РазмерКартинки.РеальныйРазмер;
	Ячейка.ГоризонтальноеПоложениеКартинки = ГоризонтальноеПоложение.Право;
	Ячейка.ВертикальноеПоложениеКартинки = ВертикальноеПоложение.Верх;
	
КонецПроцедуры

Функция ПрерватьСканированиеРезультатаОтчета(Ячейка, ИндексСтруктурыОтчета, ГраницаЗаголовкаРаздела)
	
	Если ИндексСтруктурыОтчета.Количество() = 0 Тогда 
		Возврат Истина;
	КонецЕсли;
	
	КоличествоРазделов = ИндексСтруктурыОтчета[0].КоличествоРазделов;
	
	Если КоличествоРазделов > 1 Тогда 
		Возврат Ложь;
	КонецЕсли;
	
	Если ГраницаЗаголовкаРаздела = Неопределено
		И Не ЭтоЯчейкаЗаголовкаОтчета(Ячейка) Тогда 
		
		Возврат Ложь;
	КонецЕсли;
	
	Если ГраницаЗаголовкаРаздела = Неопределено
		Или ЭтоЯчейкаЗаголовкаОтчета(Ячейка) И Ячейка.Верх - ГраницаЗаголовкаРаздела = 1 Тогда 
		
		ГраницаЗаголовкаРаздела = Ячейка.Низ;
		
		Возврат Ложь;
	КонецЕсли;
	
	Возврат Истина;
	
КонецФункции

Функция ЭтоЯчейкаЗаголовкаОтчета(Ячейка)
	
	Возврат Ячейка.РежимИзмененияРазмераКолонки = РежимИзмененияРазмера.БыстроеИзменение;
	
КонецФункции

Функция СтандартныйРазрезСвойствЗаголовковОтчета()
	
	ОписаниеЧисла = Новый ОписаниеТипов("Число");
	ОписаниеСтроки = Новый ОписаниеТипов("Строка");
	
	Свойства = Новый ТаблицаЗначений;
	Свойства.Колонки.Добавить("Верх", ОписаниеЧисла);
	Свойства.Колонки.Добавить("Лево", ОписаниеЧисла);
	Свойства.Колонки.Добавить("Низ", ОписаниеЧисла);
	Свойства.Колонки.Добавить("Право", ОписаниеЧисла);
	Свойства.Колонки.Добавить("Имя", ОписаниеСтроки);
	Свойства.Колонки.Добавить("Расшифровка");
	
	Возврат Свойства;
	
КонецФункции

// Возвращаемое значение:
//  Структура:
//    * ИдентификаторИндекса - УникальныйИдентификатор
//    * ОформитьПоложительные - Булево
//    * ОформитьОтрицательные - Булево
//    * СортироватьПоУбыванию - Булево
//    * СортироватьПоВозрастанию - Булево
//    * ПереместитьПолеНиже - Булево
//    * ПереместитьПолеВыше - Булево
//    * ПереместитьПолеВправо - Булево
//    * ПереместитьПолеВлево - Булево
//    * СгруппироватьПоВыбранномуПолю - Булево
//    * ВставитьГруппировкуНиже - Булево
//    * ВставитьГруппировкуВыше - Булево
//    * ВставитьПолеСправа - Булево
//    * ВставитьПолеСлева - Булево
//    * СкрытьПоле - Булево
//    * ПереименоватьПоле - Булево
//    * ОформитьЕще - Булево
//    * ИспользуетсяВПоляхГруппировки - Булево
//    * ТипПоля - Тип
//    * ТипЗначения - ОписаниеТипов
//    * Ресурс - Булево
//    * Измерение - Булево
//    * Период - Булево
//    * НаправлениеСортировки - НаправлениеСортировкиКомпоновкиДанных
//                            - Неопределено
//    * ПолеСортируется - Булево
//    * Поле - ПолеКомпоновкиДанных
//    * ИдентификаторПоля - ИдентификаторКомпоновкиДанных
//    * ИдентификаторГруппировки - ИдентификаторКомпоновкиДанных
//    * ИдентификаторРаздела - ИдентификаторКомпоновкиДанных
//    * ИдентификаторНастроек - ИдентификаторКомпоновкиДанных
//    * ПорядокПоля - Число
//    * ПорядокГруппировки - Число
//    * ПорядокРаздела - Число
//    * КоличествоРодительскихЗаголовков - Число
//    * КоличествоДочернихЗаголовков - Число
//    * Расшифровка - ИдентификаторРасшифровкиКомпоновкиДанных
//                  - Неопределено
//    * Право - Число
//    * Лево - Число
//    * Низ - Число
//    * Верх - Число
//    * Текст - Строка
//
Функция СтандартныеСвойстваЗаголовкаОтчета() Экспорт
	
	Свойства = Новый Структура;
	Свойства.Вставить("Текст", "");
	Свойства.Вставить("Верх", 0);
	Свойства.Вставить("Низ", 0);
	Свойства.Вставить("Лево", 0);
	Свойства.Вставить("Право", 0);
	Свойства.Вставить("Расшифровка", Неопределено);
	
	Свойства.Вставить("КоличествоДочернихЗаголовков", 0);
	Свойства.Вставить("КоличествоРодительскихЗаголовков", 0);
	
	Свойства.Вставить("ПорядокРаздела", 0);
	Свойства.Вставить("КоличествоРазделов", 0);
	Свойства.Вставить("ПорядокГруппировки", 0);
	Свойства.Вставить("ПорядокПоля", 0);
	
	Свойства.Вставить("ИдентификаторНастроек", Неопределено);
	Свойства.Вставить("ИдентификаторРаздела", Неопределено);
	Свойства.Вставить("ИдентификаторГруппировки", Неопределено);
	Свойства.Вставить("ИдентификаторПоля", Неопределено);
	
	Свойства.Вставить("Поле", Неопределено);
	Свойства.Вставить("ПолеСортируется", Ложь);
	Свойства.Вставить("НаправлениеСортировки", Неопределено);
	
	Свойства.Вставить("Период", Ложь);
	Свойства.Вставить("Измерение", Ложь);
	Свойства.Вставить("Ресурс", Ложь);
	Свойства.Вставить("ЭтоФормула", Ложь);
	
	Свойства.Вставить("ТипЗначения", Неопределено);
	Свойства.Вставить("ТипПоля", Неопределено);
	
	Свойства.Вставить("ИспользуетсяВПоляхГруппировки", Ложь);
	Свойства.Вставить("ТипГруппировки", Неопределено);
	
	Свойства.Вставить("СгруппироватьПоВыбранномуПолю", Ложь);
	
	Свойства.Вставить("ВставитьПолеСлева", Ложь);
	Свойства.Вставить("ВставитьПолеСправа", Ложь);
	Свойства.Вставить("ВставитьГруппировкуВыше", Ложь);
	Свойства.Вставить("ВставитьГруппировкуНиже", Ложь);
	
	Свойства.Вставить("ПереместитьПолеВлево", Ложь);
	Свойства.Вставить("ПереместитьПолеВправо", Ложь);
	Свойства.Вставить("ПереместитьПолеВыше", Ложь);
	Свойства.Вставить("ПереместитьПолеНиже", Ложь);
	
	Свойства.Вставить("СортироватьПоВозрастанию", Истина);
	Свойства.Вставить("СортироватьПоУбыванию", Истина);
	
	Свойства.Вставить("СкрытьПоле", Ложь);
	Свойства.Вставить("ПереименоватьПоле", Ложь);
	
	Свойства.Вставить("ОформитьОтрицательные", Ложь);
	Свойства.Вставить("ОформитьПоложительные", Ложь);
	Свойства.Вставить("ОформитьЕще", Ложь);
	
	Свойства.Вставить("ИдентификаторИндекса", Неопределено);
	
	Возврат Свойства;
	
КонецФункции

#КонецОбласти

#Область ДанныеЭлементаРасшифровки

Функция ДанныеЭлементаРасшифровки(Форма, Расшифровка) Экспорт 
	
	Если Не ВариантыОтчетовСлужебныйКлиентСервер.РежимВариантаОтчета(Форма.КлючТекущегоВарианта)
		Или Не Форма.НастройкиОтчета.РазрешеноИзменятьВарианты
		Или Не ТипЗнч(Расшифровка) = Тип("ИдентификаторРасшифровкиКомпоновкиДанных") Тогда
		
		Возврат Неопределено;
	КонецЕсли; 
	
	Отчет = Форма.Отчет;
	Документ = Форма.ОтчетТабличныйДокумент;
	ПолеДокумента = Форма.Элементы.ОтчетТабличныйДокумент;
	
	ВыделенныеОбластиДокумента = ПолеДокумента.ПолучитьВыделенныеОбласти();
	
	Данные = ПолучитьИзВременногоХранилища(Форма.ОтчетДанныеРасшифровки);
	ЭлементРасшифровки = Данные.Элементы.Получить(Расшифровка);
	
	Родители = ЭлементРасшифровки.ПолучитьРодителей();
	Родитель = ?(Родители.Количество() = 0, Неопределено, Родители[0]);
	
	Если ТипЗнч(ЭлементРасшифровки) = Тип("ЭлементРасшифровкиКомпоновкиДанныхГруппировка")
		Или ТипЗнч(Родитель) <> Тип("ЭлементРасшифровкиКомпоновкиДанныхГруппировка") Тогда 
	
		ТипЭлементаРасшифровки = ВариантыОтчетовСлужебныйКлиентСервер.ТипЭлементаРасшифровкиГруппировка();
	Иначе
		ТипЭлементаРасшифровки = ТипРеквизит();
	КонецЕсли;
	
	ДанныеЭлементаРасшифровки = Новый Структура;
	ДанныеЭлементаРасшифровки.Вставить("Тип", ТипЭлементаРасшифровки);
	ДанныеЭлементаРасшифровки.Вставить("Настройки", Данные.Настройки);
	ДанныеЭлементаРасшифровки.Вставить("Отбор", ОтборЭлементаРасшифровки(ЭлементРасшифровки));
	ДанныеЭлементаРасшифровки.Вставить("Отборы", ОтборыВыделенныхЭлементовРасшифровки(Документ, ВыделенныеОбластиДокумента, Данные));
	
	Поля = ЭлементРасшифровки.ПолучитьПоля();
	
	Если Поля.Количество() = 0 Тогда
		
		ДанныеЭлементаРасшифровки.Вставить("Значение", Неопределено);
		ДанныеЭлементаРасшифровки.Вставить("Значения", Неопределено);
		ДанныеЭлементаРасшифровки.Вставить("Поле", "");
		
	Иначе 
		
		СвойстваПоля = Поля[0];
		
		ДанныеЭлементаРасшифровки.Вставить("Значение", ?(СвойстваПоля.Значение = Null, Неопределено, СвойстваПоля.Значение));
		ДанныеЭлементаРасшифровки.Вставить("Значения", ДанныеЭлементаРасшифровки.Отборы[СвойстваПоля.Поле]);
		ДанныеЭлементаРасшифровки.Вставить("Поле", СвойстваПоля.Поле);
		
	КонецЕсли;
	
	ДанныеЭлементаРасшифровки.Вставить("ЭтоСсылка", ОбщегоНазначения.ЭтоСсылка(ТипЗнч(ДанныеЭлементаРасшифровки.Значение)));
	
	ДоступныеВидыСравнения = Новый СписокЗначений;
	
	Если ЗначениеЗаполнено(ДанныеЭлементаРасшифровки.Поле) Тогда
		
		ДоступноеПоле = Отчет.КомпоновщикНастроек.Настройки.ДоступныеПоляВыбора.НайтиПоле(
			Новый ПолеКомпоновкиДанных(ДанныеЭлементаРасшифровки.Поле));
		
		Если ДоступноеПоле = Неопределено Тогда
			
			ДанныеЭлементаРасшифровки.Вставить("ТипЗначения", Тип("Неопределено"));
			ДанныеЭлементаРасшифровки.Вставить("Ресурс", Ложь);
			
		Иначе
			
			ДанныеЭлементаРасшифровки.Вставить("ТипЗначения", ДоступноеПоле.ТипЗначения);
			ДанныеЭлементаРасшифровки.Вставить("Ресурс", ДоступноеПоле.Ресурс);
			
			Если ДанныеЭлементаРасшифровки.Значение = Неопределено Тогда 
				
				Область = ПолеДокумента.ТекущаяОбласть;
				
				Если ТипЗнч(Область) = Тип("ОбластьЯчеекТабличногоДокумента") Тогда 
					
					ДанныеЭлементаРасшифровки.Значение = ДоступноеПоле.ТипЗначения.ПривестиЗначение(Область.Текст);
					ДанныеЭлементаРасшифровки.Значения = ПриведенныеЗначенияВыделенныхОбластей(
						Документ, ВыделенныеОбластиДокумента, ДоступноеПоле.ТипЗначения);
					
				КонецЕсли;
				
			КонецЕсли;
			
		КонецЕсли; 
		
		ДоступноеПолеОтбора = Отчет.КомпоновщикНастроек.Настройки.ДоступныеПоляОтбора.НайтиПоле(
			Новый ПолеКомпоновкиДанных(ДанныеЭлементаРасшифровки.Поле));
		
		Если ДоступноеПолеОтбора <> Неопределено Тогда 
			ДоступныеВидыСравнения = ДоступноеПолеОтбора.ДоступныеВидыСравнения;
		КонецЕсли;
		
	Иначе
		
		ДанныеЭлементаРасшифровки.Вставить("ТипЗначения", Тип("Неопределено"));
		ДанныеЭлементаРасшифровки.Вставить("Ресурс", Ложь);
		
	КонецЕсли; 
	
	Если ДоступныеВидыСравнения.Количество() = 0 Тогда 
		
		Для Каждого Вид Из ВидСравненияКомпоновкиДанных Цикл 
			ДоступныеВидыСравнения.Добавить(Вид);
		КонецЦикла;
		
	КонецЕсли;
	
	Если ДоступныеВидыСравнения.НайтиПоЗначению("СнятьФильтр") = Неопределено Тогда 
		ДоступныеВидыСравнения.Вставить(0, "СнятьФильтр", НСтр("ru = 'Снять фильтр'"));
	КонецЕсли;
	
	Если ДоступныеВидыСравнения.НайтиПоЗначению("ФильтроватьЕще") = Неопределено Тогда 
		ДоступныеВидыСравнения.Добавить("ФильтроватьЕще", НСтр("ru = 'Еще...'"));
	КонецЕсли;
	
	ДанныеЭлементаРасшифровки.Вставить("ДоступныеВидыСравнения", ДоступныеВидыСравнения);
	
	Возврат ДанныеЭлементаРасшифровки;
	
КонецФункции

Функция ОтборЭлементаРасшифровки(ЭлементРасшифровки, Результат = Неопределено)
	
	Если Результат = Неопределено Тогда
		Результат = Новый Соответствие;
	КонецЕсли; 
	
	Если ТипЗнч(ЭлементРасшифровки) = Тип("ЭлементРасшифровкиКомпоновкиДанныхПоля") Тогда
		
		Поля = ЭлементРасшифровки.ПолучитьПоля();
		
		Для каждого Поле Из Поля Цикл
			
			Если Поле.Значение = Null Тогда
				Продолжить;
			КонецЕсли;
			
			Значение = Результат[Поле.Поле];
			
			Если Значение = Неопределено Тогда 
				
				Результат.Вставить(Поле.Поле, Поле.Значение);
				Продолжить;
				
			КонецЕсли;
			
			Значения = ОтчетыКлиентСервер.ЗначенияСписком(Значение);
			
			Если Значения.НайтиПоЗначению(Поле.Значение) = Неопределено Тогда 
				Значения.Добавить(Поле.Значение);
			КонецЕсли;
			
			Результат.Вставить(Поле.Поле, Значения);
			
		КонецЦикла; 
	КонецЕсли;
	
	Родители = ЭлементРасшифровки.ПолучитьРодителей();
	
	Для Каждого Родитель Из Родители Цикл
		ОтборЭлементаРасшифровки(Родитель, Результат);
	КонецЦикла;
	
	Возврат Результат;
	
КонецФункции

Функция ОтборыВыделенныхЭлементовРасшифровки(Документ, ВыделенныеОбластиДокумента, Данные)
	
	Результат = Новый Соответствие;
	
	Для Каждого ВыделеннаяОбласть Из ВыделенныеОбластиДокумента Цикл
		
		Если ТипЗнч(ВыделеннаяОбласть) <> Тип("ОбластьЯчеекТабличногоДокумента") Тогда
			Продолжить;
		КонецЕсли;
		
		Для НомерСтроки = ВыделеннаяОбласть.Верх По ВыделеннаяОбласть.Низ Цикл 
			
			Область = Документ.Область(НомерСтроки, ВыделеннаяОбласть.Лево, НомерСтроки, ВыделеннаяОбласть.Право);
			
			Если Область.ТипОбласти = ТипОбластиЯчеекТабличногоДокумента.Прямоугольник
				И ТипЗнч(Область.Расшифровка) = Тип("ИдентификаторРасшифровкиКомпоновкиДанных") Тогда 
				
				ЭлементРасшифровки = Данные.Элементы.Получить(Область.Расшифровка);
				ОтборЭлементаРасшифровки(ЭлементРасшифровки, Результат);
				
			КонецЕсли;
			
		КонецЦикла;
		
	КонецЦикла;
	
	Возврат Результат;
	
КонецФункции

Функция ПриведенныеЗначенияВыделенныхОбластей(Документ, ВыделенныеОбластиДокумента, ТипЗначения)
	
	Результат = Новый СписокЗначений;
	
	Для Каждого ВыделеннаяОбласть Из ВыделенныеОбластиДокумента Цикл
		
		Если ТипЗнч(ВыделеннаяОбласть) <> Тип("ОбластьЯчеекТабличногоДокумента") Тогда
			Продолжить;
		КонецЕсли;
		
		Для НомерСтроки = ВыделеннаяОбласть.Верх По ВыделеннаяОбласть.Низ Цикл 
			
			Область = Документ.Область(НомерСтроки, ВыделеннаяОбласть.Лево, НомерСтроки, ВыделеннаяОбласть.Право);
			
			Если Область.ТипОбласти = ТипОбластиЯчеекТабличногоДокумента.Прямоугольник Тогда 
				
				Значение = ТипЗначения.ПривестиЗначение(Область.Текст);
				
				Если Результат.НайтиПоЗначению(Значение) = Неопределено Тогда 
					Результат.Добавить(Значение);
				КонецЕсли;
				
			КонецЕсли;
			
		КонецЦикла;
		
	КонецЦикла;
	
	Возврат Результат;
	
КонецФункции

Функция ТипРеквизит()
	
	Возврат "Реквизит";	
	
КонецФункции

#КонецОбласти

#Область ЗначениеЯчейки

// Параметры:
//  ПараметрыЗаполнения - Структура:
//    * Значения - СписокЗначений
//    * СвойстваЗаголовка - см. СтандартныеСвойстваЗаголовкаОтчета
//    * Документ - ТабличныйДокумент
//    * Заголовки - Соответствие
//    * ГраницаРаздела - см. ГраницыРазделовОтчета
//    * ДанныеРасшифровки - ДанныеРасшифровкиКомпоновкиДанных
//    * КоличествоПервыхЧитаемыхСтрок - Число
//    * ВыведеныВсеЗначенияРазделаОтчета - Булево
//    * ДоступныеЗначения - СписокЗначений
//
// Возвращаемое значение:
//  Структура:
//    * Значения - СписокЗначений
//    * КоличествоСтрокВРазделеОтчета - Число
//    * ВыведеныВсеЗначенияРазделаОтчета - Булево
//
Функция ЗаполнитьЗначенияФильтра(ПараметрыЗаполнения) Экспорт 
	
	Значения = ПараметрыЗаполнения.Значения;
	СвойстваЗаголовка = ПараметрыЗаполнения.СвойстваЗаголовка;
	Документ = ПараметрыЗаполнения.Документ;
	Заголовки = ПараметрыЗаполнения.Заголовки;
	ГраницаРаздела = ПараметрыЗаполнения.ГраницаРаздела;
	ДанныеРасшифровки = ПараметрыЗаполнения.ДанныеРасшифровки;
	КоличествоПервыхЧитаемыхСтрок = ПараметрыЗаполнения.КоличествоПервыхЧитаемыхСтрок;
	ВыведеныВсеЗначенияРазделаОтчета = ПараметрыЗаполнения.ВыведеныВсеЗначенияРазделаОтчета;
	ДоступныеЗначения = ПараметрыЗаполнения.ДоступныеЗначения;
	
	ДоступныеТипы = Значения.ТипЗначения;
	ИндексЗначенийЯчеек = Новый Соответствие;
	
	КоличествоПрочтенныхСтрок = 0;
	КоличествоСтрокВРазделеОтчета = ГраницаРаздела - СвойстваЗаголовка.Низ;
	
	Если ВыведеныВсеЗначенияРазделаОтчета Тогда 
		КоличествоЧитаемыхСтрок = КоличествоСтрокВРазделеОтчета;
	Иначе
		КоличествоЧитаемыхСтрок = Мин(КоличествоПервыхЧитаемыхСтрок + СвойстваЗаголовка.Низ, КоличествоСтрокВРазделеОтчета);
	КонецЕсли;
	
	Для НомерСтроки = СвойстваЗаголовка.Низ + 1 По Документ.ВысотаТаблицы Цикл 
		
		КоличествоПрочтенныхСтрок = КоличествоПрочтенныхСтрок + 1;
		
		Если КоличествоПрочтенныхСтрок > КоличествоЧитаемыхСтрок Тогда 
			Прервать;
		КонецЕсли;
		
		Ячейка = Документ.Область(НомерСтроки, СвойстваЗаголовка.Лево);
		
		Если Заголовки[Ячейка.Имя] <> Неопределено
			Или Ячейка.ТипОбласти <> ТипОбластиЯчеекТабличногоДокумента.Прямоугольник
			Или Не ЗначениеЗаполнено(Ячейка.Текст) Тогда 
			
			Продолжить;
		КонецЕсли;
		
		ЗначениеЯчейки = ЗначениеЯчейки(Ячейка, ДоступныеТипы, ДанныеРасшифровки);
		
		Если Не ЗначениеЯчейкиКонсистентно(ЗначениеЯчейки, ИндексЗначенийЯчеек, ДоступныеТипы) Тогда 
			Продолжить;
		КонецЕсли;
		
		ДоступноеЗначение = ДоступныеЗначения.НайтиПоЗначению(ЗначениеЯчейки.Значение);
		
		Если ДоступноеЗначение = Неопределено Тогда 
			
			ЗаполнитьЗначенияСвойств(Значения.Добавить(), ЗначениеЯчейки);
			
		Иначе
			
			ДоступноеЗначение.Пометка = Истина;
			ЗаполнитьЗначенияСвойств(Значения.Добавить(), ДоступноеЗначение);
			
		КонецЕсли;
		
	КонецЦикла;
	
	ВыведеныВсеЗначенияРазделаОтчета = (КоличествоЧитаемыхСтрок = КоличествоСтрокВРазделеОтчета);
	
	РезультатЗаполнения = Новый Структура;
	РезультатЗаполнения.Вставить("Значения", Значения);
	РезультатЗаполнения.Вставить("КоличествоСтрокВРазделеОтчета", КоличествоСтрокВРазделеОтчета);
	РезультатЗаполнения.Вставить("ВыведеныВсеЗначенияРазделаОтчета", ВыведеныВсеЗначенияРазделаОтчета);
	
	Возврат РезультатЗаполнения;
	
КонецФункции

// Параметры:
//  Ячейка - ОбластьЯчеекТабличногоДокумента
//         - Структура:
//             * Текст - Строка
//             * Расшифровка - ИдентификаторРасшифровкиКомпоновкиДанных
//                           - Неопределено
//  ДоступныеТипы - ОписаниеТипов
//  ДанныеРасшифровки - ДанныеРасшифровкиКомпоновкиДанных
//
// Возвращаемое значение:
//   см. СтандартноеЗначениеЯчейки
//
Функция ЗначениеЯчейки(Ячейка, ДоступныеТипы, ДанныеРасшифровки) Экспорт 
	
	ЗначениеЯчейки = СтандартноеЗначениеЯчейки(Ячейка.Текст);
	
	КоличествоДоступныхТипов = ДоступныеТипы.Типы().Количество();
	
	Если ТипЗнч(Ячейка.Расшифровка) = Тип("ИдентификаторРасшифровкиКомпоновкиДанных") Тогда 
		
		ЭлементРасшифровки = ДанныеРасшифровки.Элементы[Ячейка.Расшифровка];
		Поля = ЭлементРасшифровки.ПолучитьПоля();
		
		Если Поля.Количество() > 0 Тогда 
			
			Значение = Поля[0].Значение;
			
			Если КоличествоДоступныхТипов = 0 Тогда 
				
				ЗначениеЯчейки.Значение = Значение;
				
			ИначеЕсли ЗначениеЗаполнено(Значение)
				И Не ДоступныеТипы.СодержитТип(ТипЗнч(Значение)) Тогда 
				
				ЗначениеЯчейки.Значение = Null;
				
			ИначеЕсли Значение = Null Тогда 
				
				ЗначениеЯчейки.Значение = ДоступныеТипы.ПривестиЗначение(Ячейка.Текст);
				
			Иначе
				
				ЗначениеЯчейки.Значение = ДоступныеТипы.ПривестиЗначение(Значение);
				
			КонецЕсли;
			
			Если ЗначениеЯчейки.Значение = Неопределено Тогда 
				ЗначениеЯчейки.Значение = Null;
			КонецЕсли;
			
			Возврат ЗначениеЯчейки;
			
		КонецЕсли;
		
	КонецЕсли;
	
	Если ОбщегоНазначенияКлиентСервер.ЭтоЧисло(Ячейка.Текст) Тогда 
		
		ОписаниеЧисла = Новый ОписаниеТипов("Число");
		ЗначениеЯчейки.Значение = ОписаниеЧисла.ПривестиЗначение(Ячейка.Текст);
		Возврат ЗначениеЯчейки;
		
	КонецЕсли;
	
	Значение = ОбщегоНазначенияКлиентСервер.СтрокаВДату(ЗначениеЯчейки.Значение);
	
	Если ЗначениеЗаполнено(Значение) Тогда 
		ЗначениеЯчейки.Значение = Значение;
	Иначе
		ЗначениеЯчейки.Значение = ДоступныеТипы.ПривестиЗначение(Значение);
	КонецЕсли;
	
	Возврат ЗначениеЯчейки;
	
КонецФункции

Функция ЗначениеЯчейкиКонсистентно(ЗначениеЯчейки, ИндексЗначенийЯчеек, ДоступныеТипы)
	
	Если Не ЗначениеЗаполнено(ЗначениеЯчейки.Значение)
		И ЗначениеЗаполнено(ЗначениеЯчейки.Представление) Тогда 
		
		Возврат Ложь;
	КонецЕсли;
	
	Если ИндексЗначенийЯчеек[ЗначениеЯчейки.Значение] <> Неопределено Тогда 
		Возврат Ложь;
	КонецЕсли;
	
	КоличествоДоступныхТипов = ДоступныеТипы.Типы().Количество();
	
	Если КоличествоДоступныхТипов > 0
		И Не ДоступныеТипы.СодержитТип(ТипЗнч(ЗначениеЯчейки.Значение)) Тогда 
		
		Возврат Ложь;
	КонецЕсли;
	
	ИндексЗначенийЯчеек.Вставить(ЗначениеЯчейки.Значение, Истина);
	
	Возврат Истина;
	
КонецФункции

// Параметры:
//  Значение - Строка
//
// Возвращаемое значение:
//   Структура:
//     * Значение - Строка
//     * Представление - Строка
//     * Пометка - Булево
//
Функция СтандартноеЗначениеЯчейки(Значение)
	
	ЗначениеЯчейки = Новый Структура;
	ЗначениеЯчейки.Вставить("Значение", Значение);
	ЗначениеЯчейки.Вставить("Представление", Значение);
	ЗначениеЯчейки.Вставить("Пометка", Истина);
	
	Возврат ЗначениеЯчейки;
	
КонецФункции

#КонецОбласти

#Область РасшифровкаПоДетальнымЗаписям

Процедура ПодготовитьНастройкиОтчетаКРасшифровкеПоДетальнымЗаписям(Форма, НастройкиВарианта, ПрименяемыеНастройки) Экспорт 
	
	ДействиеОбработкиРасшифровки = ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(
		ПрименяемыеНастройки.ДополнительныеСвойства, "ДействиеОбработкиРасшифровки");
	
	Если Не ЗначениеЗаполнено(ДействиеОбработкиРасшифровки) Тогда 
		Возврат;
	КонецЕсли;
	
	СвойстваЗаголовка = ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(
		ПрименяемыеНастройки.ДополнительныеСвойства, "СвойстваЗаголовка");
	
	Если ТипЗнч(НастройкиВарианта) = Тип("НастройкиКомпоновкиДанных") Тогда 
		Настройки = НастройкиВарианта;
	Иначе
		Настройки = Форма.Отчет.КомпоновщикНастроек.Настройки;
	КонецЕсли;
	
	УдалитьНеактуальныеРазделаОтчета(Настройки, СвойстваЗаголовка);
	ПодготовитьСтруктуруРазделаОтчетаКРасшифровке(Настройки);
	
	НастройкиВарианта = Настройки;
	
КонецПроцедуры

Процедура УдалитьНеактуальныеРазделаОтчета(Настройки, СвойстваЗаголовка)
	
	ИндексРаздела = Настройки.Структура.Количество() - 1;
	
	Пока ИндексРаздела >= 0 Цикл 
		
		Раздел = Настройки.Структура[ИндексРаздела];
		
		Если Не Раздел.Использование
			Или ТипЗнч(Раздел) <> Тип("ГруппировкаКомпоновкиДанных")
			И ТипЗнч(Раздел) <> Тип("ТаблицаКомпоновкиДанных") Тогда 
			
			Настройки.Структура.Удалить(Раздел);
		КонецЕсли;
		
		ИндексРаздела = ИндексРаздела - 1;
		
	КонецЦикла;
	
	НомерТекущегоРаздела = СвойстваЗаголовка.ПорядокРаздела;
	КоличествоРазделов = Настройки.Структура.Количество();
	РазделыНаУдаление = Новый Массив;
	
	Для НомерРаздела = 1 По КоличествоРазделов Цикл 
		
		Если НомерРаздела <> НомерТекущегоРаздела Тогда 
			РазделыНаУдаление.Добавить(Настройки.Структура[НомерРаздела - 1]);
		КонецЕсли;
		
	КонецЦикла;
	
	Для Каждого Раздел Из РазделыНаУдаление Цикл 
		Настройки.Структура.Удалить(Раздел);
	КонецЦикла;
	
КонецПроцедуры

Процедура ПодготовитьСтруктуруРазделаОтчетаКРасшифровке(Настройки)
	
	Если Настройки.Структура.Количество() <> 1 Тогда 
		Возврат;
	КонецЕсли;
	
	ЭлементСтруктуры = Настройки.Структура[0];
	Группировка = Неопределено;
	
	Если ТипЗнч(ЭлементСтруктуры) = Тип("ГруппировкаКомпоновкиДанных") Тогда 
		
		Группировка = ЭлементСтруктуры;
		
	ИначеЕсли ТипЗнч(ЭлементСтруктуры) = Тип("ТаблицаКомпоновкиДанных") Тогда 
		
		Если ЭлементСтруктуры.Строки.Количество() > 0 Тогда 
			Группировка = ЭлементСтруктуры.Строки[0];
		КонецЕсли;
		
	КонецЕсли;
	
	Если Группировка = Неопределено Тогда 
		Возврат;
	КонецЕсли;
	
	Группировка.Структура.Очистить();
	Группировка.ПоляГруппировки.Элементы.Очистить();
	
КонецПроцедуры

Функция СвойстваОтбораОбработчикаРасшифровкиПоДетальнымЗаписям() Экспорт
	
	СвойстваЭлементаОтбора = Новый Структура;
	СвойстваЭлементаОтбора.Вставить("Значение", Неопределено);
	СвойстваЭлементаОтбора.Вставить("ВидСравнения", ВидСравненияКомпоновкиДанных.Равно);
	СвойстваЭлементаОтбора.Вставить("РежимОтображения", РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный);
	СвойстваЭлементаОтбора.Вставить("Представление", "");
	СвойстваЭлементаОтбора.Вставить("ИдентификаторПользовательскойНастройки", "");
	
	Возврат СвойстваЭлементаОтбора;
	
КонецФункции

#КонецОбласти

#КонецОбласти
